rippled
Loading...
Searching...
No Matches
BuildLedger.cpp
1#include <xrpld/app/ledger/BuildLedger.h>
2#include <xrpld/app/ledger/Ledger.h>
3#include <xrpld/app/ledger/LedgerReplay.h>
4#include <xrpld/app/ledger/OpenLedger.h>
5#include <xrpld/app/misc/CanonicalTXSet.h>
6#include <xrpld/app/tx/apply.h>
7
8#include <xrpl/protocol/Feature.h>
9
10namespace ripple {
11
12/* Generic buildLedgerImpl that dispatches to ApplyTxs invocable with signature
13 void(OpenView&, std::shared_ptr<Ledger> const&)
14 It is responsible for adding transactions to the open view to generate the
15 new ledger. It is generic since the mechanics differ for consensus
16 generated ledgers versus replayed ledgers.
17*/
18template <class ApplyTxs>
22 NetClock::time_point closeTime,
23 bool const closeTimeCorrect,
24 NetClock::duration closeResolution,
25 Application& app,
27 ApplyTxs&& applyTxs)
28{
29 auto built = std::make_shared<Ledger>(*parent, closeTime);
30
31 if (built->isFlagLedger())
32 {
33 built->updateNegativeUNL();
34 }
35
36 // Set up to write SHAMap changes to our database,
37 // perform updates, extract changes
38
39 {
40 OpenView accum(&*built);
41 XRPL_ASSERT(
42 !accum.open(), "ripple::buildLedgerImpl : valid ledger state");
43 applyTxs(accum, built);
44 accum.apply(*built);
45 }
46
47 built->updateSkipList();
48 {
49 // Write the final version of all modified SHAMap
50 // nodes to the node store to preserve the new LCL
51
52 int const asf = built->stateMap().flushDirty(hotACCOUNT_NODE);
53 int const tmf = built->txMap().flushDirty(hotTRANSACTION_NODE);
54 JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf
55 << " transaction nodes";
56 }
57 built->unshare();
58
59 // Accept ledger
60 XRPL_ASSERT(
61 built->info().seq < XRP_LEDGER_EARLIEST_FEES ||
62 built->read(keylet::fees()),
63 "ripple::buildLedgerImpl : valid ledger fees");
64 built->setAccepted(closeTime, closeResolution, closeTimeCorrect);
65
66 return built;
67}
68
81 Application& app,
83 CanonicalTXSet& txns,
84 std::set<TxID>& failed,
85 OpenView& view,
87{
88 bool certainRetry = true;
89 std::size_t count = 0;
90
91 // Attempt to apply all of the retriable transactions
92 for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
93 {
94 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
95 << " begins (" << txns.size() << " transactions)";
96 int changes = 0;
97
98 auto it = txns.begin();
99
100 while (it != txns.end())
101 {
102 auto const txid = it->first.getTXID();
103
104 try
105 {
106 if (pass == 0 && built->txExists(txid))
107 {
108 it = txns.erase(it);
109 continue;
110 }
111
112 switch (applyTransaction(
113 app, view, *it->second, certainRetry, tapNONE, j))
114 {
116 it = txns.erase(it);
117 ++changes;
118 break;
119
121 failed.insert(txid);
122 it = txns.erase(it);
123 break;
124
126 ++it;
127 }
128 }
129 catch (std::exception const& ex)
130 {
131 JLOG(j.warn())
132 << "Transaction " << txid << " throws: " << ex.what();
133 failed.insert(txid);
134 it = txns.erase(it);
135 }
136 }
137
138 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
139 << " completed (" << changes << " changes)";
140
141 // Accumulate changes.
142 count += changes;
143
144 // A non-retry pass made no changes
145 if (!changes && !certainRetry)
146 break;
147
148 // Stop retriable passes
149 if (!changes || (pass >= LEDGER_RETRY_PASSES))
150 certainRetry = false;
151 }
152
153 // If there are any transactions left, we must have
154 // tried them in at least one final pass
155 XRPL_ASSERT(
156 txns.empty() || !certainRetry,
157 "ripple::applyTransactions : retry transactions");
158 return count;
159}
160
161// Build a ledger from consensus transactions
164 std::shared_ptr<Ledger const> const& parent,
165 NetClock::time_point closeTime,
166 bool const closeTimeCorrect,
167 NetClock::duration closeResolution,
168 Application& app,
169 CanonicalTXSet& txns,
170 std::set<TxID>& failedTxns,
172{
173 JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close "
174 << closeTime.time_since_epoch().count()
175 << (closeTimeCorrect ? "" : " (incorrect)");
176
177 return buildLedgerImpl(
178 parent,
179 closeTime,
180 closeTimeCorrect,
181 closeResolution,
182 app,
183 j,
184 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
185 JLOG(j.debug())
186 << "Attempting to apply " << txns.size() << " transactions";
187
188 auto const applied =
189 applyTransactions(app, built, txns, failedTxns, accum, j);
190
191 if (!txns.empty() || !failedTxns.empty())
192 JLOG(j.debug())
193 << "Applied " << applied << " transactions; "
194 << failedTxns.size() << " failed and " << txns.size()
195 << " will be retried. "
196 << "Total transactions in ledger (including Inner Batch): "
197 << accum.txCount();
198 else
199 JLOG(j.debug())
200 << "Applied " << applied << " transactions. "
201 << "Total transactions in ledger (including Inner Batch): "
202 << accum.txCount();
203 });
204}
205
206// Build a ledger by replaying
209 LedgerReplay const& replayData,
210 ApplyFlags applyFlags,
211 Application& app,
213{
214 auto const& replayLedger = replayData.replay();
215
216 JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->info().hash;
217
218 return buildLedgerImpl(
219 replayData.parent(),
220 replayLedger->info().closeTime,
221 ((replayLedger->info().closeFlags & sLCF_NoConsensusTime) == 0),
222 replayLedger->info().closeTimeResolution,
223 app,
224 j,
225 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
226 for (auto& tx : replayData.orderedTxns())
227 applyTransaction(app, accum, *tx.second, false, applyFlags, j);
228 });
229}
230
231} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:41
Stream debug() const
Definition Journal.h:309
Stream warn() const
Definition Journal.h:321
Holds transactions which were deferred to the next pass of consensus.
const_iterator end() const
const_iterator begin() const
const_iterator erase(const_iterator const &it)
uint256 const & key() const
std::shared_ptr< Ledger const > const & parent() const
std::shared_ptr< Ledger const > const & replay() const
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:46
std::size_t txCount() const
Return the number of tx inserted since creation.
Definition OpenView.cpp:103
bool open() const override
Returns true if this reflects an open ledger.
Definition OpenView.h:172
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:109
T empty(T... args)
T insert(T... args)
T is_same_v
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:203
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::size_t applyTransactions(Application &app, std::shared_ptr< Ledger const > const &built, CanonicalTXSet &txns, std::set< TxID > &failed, OpenView &view, beast::Journal j)
Apply a set of consensus transactions to a ledger.
std::shared_ptr< Ledger > buildLedgerImpl(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, bool const closeTimeCorrect, NetClock::duration closeResolution, Application &app, beast::Journal j, ApplyTxs &&applyTxs)
@ Success
Applied to this ledger.
@ Retry
Should be retried in this ledger.
@ Fail
Should not be retried in this ledger.
@ hotACCOUNT_NODE
Definition NodeObject.h:16
@ hotTRANSACTION_NODE
Definition NodeObject.h:17
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
static std::uint32_t const sLCF_NoConsensusTime
std::shared_ptr< Ledger > buildLedger(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, bool const closeTimeCorrect, NetClock::duration closeResolution, Application &app, CanonicalTXSet &txns, std::set< TxID > &failedTxs, beast::Journal j)
Build a new ledger by applying consensus transactions.
@ tapNONE
Definition ApplyView.h:12
ApplyTransactionResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition apply.cpp:220
T size(T... args)
T time_since_epoch(T... args)
T what(T... args)