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
23#include <xrpld/app/ledger/LedgerHistory.h>
24#include <xrpld/app/ledger/LedgerMaster.h>
25#include <xrpld/app/tx/apply.h>
26
27#include <xrpl/beast/insight/NullCollector.h>
28#include <xrpl/beast/unit_test.h>
29#include <xrpl/ledger/OpenView.h>
30
31#include <chrono>
32#include <sstream>
33
34namespace ripple {
35namespace test {
36
38{
39public:
50 jtx::Env& env,
51 LedgerHistory& lh,
52 NetClock::duration closeOffset,
54 {
55 if (!prev)
56 {
57 assert(!stx);
60 env.app().config(),
62 env.app().getNodeFamily());
63 }
64 auto res = std::make_shared<Ledger>(
65 *prev, prev->info().closeTime + closeOffset);
66
67 if (stx)
68 {
69 OpenView accum(&*res);
71 env.app(), accum, *stx, false, tapNONE, env.journal);
72 accum.apply(*res);
73 }
74 res->updateSkipList();
75
76 {
77 res->stateMap().flushDirty(hotACCOUNT_NODE);
78 res->txMap().flushDirty(hotTRANSACTION_NODE);
79 }
80 res->unshare();
81
82 // Accept ledger
83 res->setAccepted(
84 res->info().closeTime,
85 res->info().closeTimeResolution,
86 true /* close time correct*/);
87 lh.insert(res, false);
88 return res;
89 }
90
91 void
93 {
94 testcase("LedgerHistory mismatch");
95 using namespace jtx;
96 using namespace std::chrono;
97
98 // No mismatch
99 {
100 bool found = false;
101 Env env{
102 *this,
103 envconfig(),
104 std::make_unique<CheckMessageLogs>("MISMATCH ", &found)};
106 auto const genesis = makeLedger({}, env, lh, 0s);
107 uint256 const dummyTxHash{1};
108 lh.builtLedger(genesis, dummyTxHash, {});
109 lh.validatedLedger(genesis, dummyTxHash);
110
111 BEAST_EXPECT(!found);
112 }
113
114 // Close time mismatch
115 {
116 bool found = false;
117 Env env{
118 *this,
119 envconfig(),
121 "MISMATCH on close time", &found)};
123 auto const genesis = makeLedger({}, env, lh, 0s);
124 auto const ledgerA = makeLedger(genesis, env, lh, 4s);
125 auto const ledgerB = makeLedger(genesis, env, lh, 40s);
126
127 uint256 const dummyTxHash{1};
128 lh.builtLedger(ledgerA, dummyTxHash, {});
129 lh.validatedLedger(ledgerB, dummyTxHash);
130
131 BEAST_EXPECT(found);
132 }
133
134 // Prior ledger mismatch
135 {
136 bool found = false;
137 Env env{
138 *this,
139 envconfig(),
141 "MISMATCH on prior ledger", &found)};
143 auto const genesis = makeLedger({}, env, lh, 0s);
144 auto const ledgerA = makeLedger(genesis, env, lh, 4s);
145 auto const ledgerB = makeLedger(genesis, env, lh, 40s);
146 auto const ledgerAC = makeLedger(ledgerA, env, lh, 4s);
147 auto const ledgerBD = makeLedger(ledgerB, env, lh, 4s);
148
149 uint256 const dummyTxHash{1};
150 lh.builtLedger(ledgerAC, dummyTxHash, {});
151 lh.validatedLedger(ledgerBD, dummyTxHash);
152
153 BEAST_EXPECT(found);
154 }
155
156 // Simulate a bug in which consensus may agree on transactions, but
157 // somehow generate different ledgers
158 for (bool const txBug : {true, false})
159 {
160 std::string const msg = txBug
161 ? "MISMATCH with same consensus transaction set"
162 : "MISMATCH on consensus transaction set";
163 bool found = false;
164 Env env{
165 *this,
166 envconfig(),
169
170 Account alice{"A1"};
171 Account bob{"A2"};
172 env.fund(XRP(1000), alice, bob);
173 env.close();
174
175 auto const ledgerBase =
177
178 JTx txAlice = env.jt(noop(alice));
179 auto const ledgerA =
180 makeLedger(ledgerBase, env, lh, 4s, txAlice.stx);
181
182 JTx txBob = env.jt(noop(bob));
183 auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx);
184
185 lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {});
186 // Simulate the bug by claiming ledgerB had the same consensus hash
187 // as ledgerA, but somehow generated different ledgers
189 ledgerB,
190 txBug ? txAlice.stx->getTransactionID()
191 : txBob.stx->getTransactionID());
192
193 BEAST_EXPECT(found);
194 }
195 }
196
197 void
198 run() override
199 {
201 }
202};
203
204BEAST_DEFINE_TESTSUITE(LedgerHistory, app, ripple);
205
206} // namespace test
207} // namespace ripple
static std::shared_ptr< Collector > New()
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
virtual Config & config()=0
virtual Family & getNodeFamily()=0
virtual LedgerMaster & getLedgerMaster()=0
Retains historical ledgers.
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()
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:65
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:39
A transaction testing environment.
Definition Env.h:121
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:505
Application & app()
Definition Env.h:261
beast::Journal const journal
Definition Env.h:162
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:279
T is_same_v
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:54
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:105
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
@ hotACCOUNT_NODE
Definition NodeObject.h:35
@ hotTRANSACTION_NODE
Definition NodeObject.h:36
create_genesis_t const create_genesis
Definition Ledger.cpp:51
@ 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:241
Execution context for applying a JSON transaction.
Definition JTx.h:45
std::shared_ptr< STTx const > stx
Definition JTx.h:56