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 #include <test/jtx/CheckMessageLogs.h>
31 
32 namespace ripple {
33 namespace test {
34 
35 class LedgerHistory_test : public beast::unit_test::suite
36 {
37 public:
48  jtx::Env& env,
49  LedgerHistory& lh,
50  NetClock::duration closeOffset,
52  {
53  if (!prev)
54  {
55  assert(!stx);
56  return std::make_shared<Ledger>(
58  env.app().config(),
60  env.app().getNodeFamily());
61  }
62  auto res = std::make_shared<Ledger>(
63  *prev, prev->info().closeTime + closeOffset);
64 
65  if (stx)
66  {
67  OpenView accum(&*res);
69  env.app(), accum, *stx, false, tapNONE, env.journal);
70  accum.apply(*res);
71  }
72  res->updateSkipList();
73 
74  {
75  res->stateMap().flushDirty(hotACCOUNT_NODE);
76  res->txMap().flushDirty(hotTRANSACTION_NODE);
77  }
78  res->unshare();
79 
80  // Accept ledger
81  res->setAccepted(
82  res->info().closeTime,
83  res->info().closeTimeResolution,
84  true /* close time correct*/,
85  env.app().config());
86  lh.insert(res, false);
87  return res;
88  }
89 
90  void
92  {
93  testcase("LedgerHistory mismatch");
94  using namespace jtx;
95  using namespace std::chrono;
96 
97  // No mismatch
98  {
99  bool found = false;
100  Env env{
101  *this,
102  envconfig(),
103  std::make_unique<CheckMessageLogs>("MISMATCH ", &found)};
105  auto const genesis = makeLedger({}, env, lh, 0s);
106  uint256 const dummyTxHash{1};
107  lh.builtLedger(genesis, dummyTxHash, {});
108  lh.validatedLedger(genesis, dummyTxHash);
109 
110  BEAST_EXPECT(!found);
111  }
112 
113  // Close time mismatch
114  {
115  bool found = false;
116  Env env{
117  *this,
118  envconfig(),
119  std::make_unique<CheckMessageLogs>(
120  "MISMATCH on close time", &found)};
122  auto const genesis = makeLedger({}, env, lh, 0s);
123  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
124  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
125 
126  uint256 const dummyTxHash{1};
127  lh.builtLedger(ledgerA, dummyTxHash, {});
128  lh.validatedLedger(ledgerB, dummyTxHash);
129 
130  BEAST_EXPECT(found);
131  }
132 
133  // Prior ledger mismatch
134  {
135  bool found = false;
136  Env env{
137  *this,
138  envconfig(),
139  std::make_unique<CheckMessageLogs>(
140  "MISMATCH on prior ledger", &found)};
142  auto const genesis = makeLedger({}, env, lh, 0s);
143  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
144  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
145  auto const ledgerAC = makeLedger(ledgerA, env, lh, 4s);
146  auto const ledgerBD = makeLedger(ledgerB, env, lh, 4s);
147 
148  uint256 const dummyTxHash{1};
149  lh.builtLedger(ledgerAC, dummyTxHash, {});
150  lh.validatedLedger(ledgerBD, dummyTxHash);
151 
152  BEAST_EXPECT(found);
153  }
154 
155  // Simulate a bug in which consensus may agree on transactions, but
156  // somehow generate different ledgers
157  for (bool const txBug : {true, false})
158  {
159  std::string const msg = txBug
160  ? "MISMATCH with same consensus transaction set"
161  : "MISMATCH on consensus transaction set";
162  bool found = false;
163  Env env{
164  *this,
165  envconfig(),
166  std::make_unique<CheckMessageLogs>(msg, &found)};
168 
169  Account alice{"A1"};
170  Account bob{"A2"};
171  env.fund(XRP(1000), alice, bob);
172  env.close();
173 
174  auto const ledgerBase =
176 
177  JTx txAlice = env.jt(noop(alice));
178  auto const ledgerA =
179  makeLedger(ledgerBase, env, lh, 4s, txAlice.stx);
180 
181  JTx txBob = env.jt(noop(bob));
182  auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx);
183 
184  lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {});
185  // Simulate the bug by claiming ledgerB had the same consensus hash
186  // as ledgerA, but somehow generated different ledgers
187  lh.validatedLedger(
188  ledgerB,
189  txBug ? txAlice.stx->getTransactionID()
190  : txBob.stx->getTransactionID());
191 
192  BEAST_EXPECT(found);
193  }
194  }
195 
196  void
197  run() override
198  {
200  }
201 };
202 
204 
205 } // namespace test
206 } // namespace ripple
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
sstream
ripple::Application::getNodeFamily
virtual Family & getNodeFamily()=0
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
std::shared_ptr< Ledger >
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
std::vector
STL class.
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:197
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:46
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:439
std::chrono::duration
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
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:35
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::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::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::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::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:105
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
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:121
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:62
ripple::test::LedgerHistory_test::testHandleMismatch
void testHandleMismatch()
Definition: LedgerHistory_test.cpp:91
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
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:115
std::chrono