rippled
Loading...
Searching...
No Matches
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 <test/jtx.h>
21#include <test/jtx/CheckMessageLogs.h>
22#include <xrpld/app/ledger/LedgerHistory.h>
23#include <xrpld/app/ledger/LedgerMaster.h>
24#include <xrpld/app/tx/apply.h>
25#include <xrpld/ledger/OpenView.h>
26#include <xrpl/beast/insight/NullCollector.h>
27#include <xrpl/beast/unit_test.h>
28#include <chrono>
29#include <memory>
30#include <sstream>
31
32namespace ripple {
33namespace test {
34
36{
37public:
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 lh.insert(res, false);
86 return res;
87 }
88
89 void
91 {
92 testcase("LedgerHistory mismatch");
93 using namespace jtx;
94 using namespace std::chrono;
95
96 // No mismatch
97 {
98 bool found = false;
99 Env env{
100 *this,
101 envconfig(),
102 std::make_unique<CheckMessageLogs>("MISMATCH ", &found)};
104 auto const genesis = makeLedger({}, env, lh, 0s);
105 uint256 const dummyTxHash{1};
106 lh.builtLedger(genesis, dummyTxHash, {});
107 lh.validatedLedger(genesis, dummyTxHash);
108
109 BEAST_EXPECT(!found);
110 }
111
112 // Close time mismatch
113 {
114 bool found = false;
115 Env env{
116 *this,
117 envconfig(),
118 std::make_unique<CheckMessageLogs>(
119 "MISMATCH on close time", &found)};
121 auto const genesis = makeLedger({}, env, lh, 0s);
122 auto const ledgerA = makeLedger(genesis, env, lh, 4s);
123 auto const ledgerB = makeLedger(genesis, env, lh, 40s);
124
125 uint256 const dummyTxHash{1};
126 lh.builtLedger(ledgerA, dummyTxHash, {});
127 lh.validatedLedger(ledgerB, dummyTxHash);
128
129 BEAST_EXPECT(found);
130 }
131
132 // Prior ledger mismatch
133 {
134 bool found = false;
135 Env env{
136 *this,
137 envconfig(),
138 std::make_unique<CheckMessageLogs>(
139 "MISMATCH on prior ledger", &found)};
141 auto const genesis = makeLedger({}, env, lh, 0s);
142 auto const ledgerA = makeLedger(genesis, env, lh, 4s);
143 auto const ledgerB = makeLedger(genesis, env, lh, 40s);
144 auto const ledgerAC = makeLedger(ledgerA, env, lh, 4s);
145 auto const ledgerBD = makeLedger(ledgerB, env, lh, 4s);
146
147 uint256 const dummyTxHash{1};
148 lh.builtLedger(ledgerAC, dummyTxHash, {});
149 lh.validatedLedger(ledgerBD, dummyTxHash);
150
151 BEAST_EXPECT(found);
152 }
153
154 // Simulate a bug in which consensus may agree on transactions, but
155 // somehow generate different ledgers
156 for (bool const txBug : {true, false})
157 {
158 std::string const msg = txBug
159 ? "MISMATCH with same consensus transaction set"
160 : "MISMATCH on consensus transaction set";
161 bool found = false;
162 Env env{
163 *this,
164 envconfig(),
165 std::make_unique<CheckMessageLogs>(msg, &found)};
167
168 Account alice{"A1"};
169 Account bob{"A2"};
170 env.fund(XRP(1000), alice, bob);
171 env.close();
172
173 auto const ledgerBase =
175
176 JTx txAlice = env.jt(noop(alice));
177 auto const ledgerA =
178 makeLedger(ledgerBase, env, lh, 4s, txAlice.stx);
179
180 JTx txBob = env.jt(noop(bob));
181 auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx);
182
183 lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {});
184 // Simulate the bug by claiming ledgerB had the same consensus hash
185 // as ledgerA, but somehow generated different ledgers
187 ledgerB,
188 txBug ? txAlice.stx->getTransactionID()
189 : txBob.stx->getTransactionID());
190
191 BEAST_EXPECT(found);
192 }
193 }
194
195 void
196 run() override
197 {
199 }
200};
201
202BEAST_DEFINE_TESTSUITE(LedgerHistory, app, ripple);
203
204} // namespace test
205} // namespace ripple
static std::shared_ptr< Collector > New()
A testsuite class.
Definition: suite.h:53
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
virtual Config & config()=0
virtual Family & getNodeFamily()=0
virtual LedgerMaster & getLedgerMaster()=0
Retains historical ledgers.
Definition: LedgerHistory.h:37
void builtLedger(std::shared_ptr< Ledger const > const &, uint256 const &consensusHash, Json::Value)
Report that we have locally built a particular ledger.
bool insert(std::shared_ptr< Ledger const > const &ledger, bool validated)
Track a ledger.
void validatedLedger(std::shared_ptr< Ledger const > const &, std::optional< uint256 > const &consensusHash)
Report that we have validated a particular ledger.
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:80
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:56
void run() override
Runs the suite.
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...
Immutable cryptographic account descriptor.
Definition: Account.h:38
A transaction testing environment.
Definition: Env.h:117
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:490
Application & app()
Definition: Env.h:255
beast::Journal const journal
Definition: Env.h:158
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:237
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:54
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:104
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
@ hotTRANSACTION_NODE
Definition: NodeObject.h:36
create_genesis_t const create_genesis
Definition: Ledger.cpp:60
@ tapNONE
Definition: ApplyView.h:31
ApplyTransactionResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:125
Execution context for applying a JSON transaction.
Definition: JTx.h:44
std::shared_ptr< STTx const > stx
Definition: JTx.h:54