xrpld
Loading...
Searching...
No Matches
BuildLedger.cpp
1#include <xrpld/app/ledger/BuildLedger.h>
2
3#include <xrpld/app/ledger/LedgerReplay.h>
4#include <xrpld/app/ledger/OpenLedger.h>
5#include <xrpld/app/main/Application.h>
6
7#include <xrpl/basics/Log.h>
8#include <xrpl/basics/chrono.h>
9#include <xrpl/beast/utility/Journal.h>
10#include <xrpl/beast/utility/instrumentation.h>
11#include <xrpl/ledger/ApplyView.h>
12#include <xrpl/ledger/CanonicalTXSet.h>
13#include <xrpl/ledger/Ledger.h>
14#include <xrpl/ledger/OpenView.h>
15#include <xrpl/ledger/entries/FeeSettingsEntry.h>
16#include <xrpl/nodestore/NodeObject.h>
17#include <xrpl/protocol/Indexes.h> // IWYU pragma: keep
18#include <xrpl/protocol/LedgerHeader.h>
19#include <xrpl/protocol/Protocol.h>
20#include <xrpl/protocol/SystemParameters.h> // IWYU pragma: keep
21#include <xrpl/protocol/TxFlags.h>
22#include <xrpl/tx/apply.h>
23
24#include <cstddef>
25#include <exception>
26#include <memory>
27#include <set>
28
29namespace xrpl {
30
31/* Generic buildLedgerImpl that dispatches to ApplyTxs invocable with signature
32 void(OpenView&, std::shared_ptr<Ledger> const&)
33 It is responsible for adding transactions to the open view to generate the
34 new ledger. It is generic since the mechanics differ for consensus
35 generated ledgers versus replayed ledgers.
36*/
37template <class ApplyTxs>
38std::shared_ptr<Ledger>
41 NetClock::time_point closeTime,
42 bool const closeTimeCorrect,
43 NetClock::duration closeResolution,
44 Application& app,
46 ApplyTxs&& applyTxs)
47{
48 auto built = std::make_shared<Ledger>(*parent, closeTime);
49
50 if (built->isFlagLedger())
51 {
52 built->updateNegativeUNL();
53 }
54
55 // Set up to write SHAMap changes to our database,
56 // perform updates, extract changes
57
58 {
59 OpenView accum(&*built);
60 XRPL_ASSERT(!accum.open(), "xrpl::buildLedgerImpl : valid ledger state");
61 applyTxs(accum, built);
62 accum.apply(*built);
63 }
64
65 built->updateSkipList();
66 {
67 // Write the final version of all modified SHAMap
68 // nodes to the node store to preserve the new LCL
69
70 int const asf = built->stateMap().flushDirty(NodeObjectType::AccountNode);
71 int const tmf = built->txMap().flushDirty(NodeObjectType::TransactionNode);
72 JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf << " transaction nodes";
73 }
74 built->unshare();
75
76 // Accept ledger
77 XRPL_ASSERT(
78 built->header().seq < kXrpLedgerEarliestFees || FeeSettingsEntryR(*built),
79 "xrpl::buildLedgerImpl : valid ledger fees");
80 built->setAccepted(closeTime, closeResolution, closeTimeCorrect);
81
82 return built;
83}
84
95
98 Application& app,
100 CanonicalTXSet& txns,
101 std::set<TxID>& failed,
102 OpenView& view,
104{
105 bool certainRetry = true;
106 std::size_t count = 0;
107
108 // Attempt to apply all of the retriable transactions
109 for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
110 {
111 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " begins ("
112 << txns.size() << " transactions)";
113 int changes = 0;
114
115 auto it = txns.begin();
116
117 while (it != txns.end())
118 {
119 auto const txid = it->first.getTXID();
120
121 try
122 {
123 if (pass == 0 && built->txExists(txid))
124 {
125 it = txns.erase(it);
126 continue;
127 }
128
129 switch (applyTransaction(app, view, *it->second, certainRetry, TapNone, j))
130 {
132 it = txns.erase(it);
133 ++changes;
134 break;
135
137 failed.insert(txid);
138 it = txns.erase(it);
139 break;
140
142 ++it;
143 }
144 }
145 catch (std::exception const& ex)
146 {
147 JLOG(j.warn()) << "Transaction " << txid << " throws: " << ex.what();
148 failed.insert(txid);
149 it = txns.erase(it);
150 }
151 }
152
153 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " completed ("
154 << changes << " changes)";
155
156 // Accumulate changes.
157 count += changes;
158
159 // A non-retry pass made no changes
160 if ((changes == 0) && !certainRetry)
161 break;
162
163 // Stop retriable passes
164 if ((changes == 0) || (pass >= LEDGER_RETRY_PASSES))
165 certainRetry = false;
166 }
167
168 // If there are any transactions left, we must have
169 // tried them in at least one final pass
170 XRPL_ASSERT(txns.empty() || !certainRetry, "xrpl::applyTransactions : retry transactions");
171 return count;
172}
173
174// Build a ledger from consensus transactions
177 std::shared_ptr<Ledger const> const& parent,
178 NetClock::time_point closeTime,
179 bool const closeTimeCorrect,
180 NetClock::duration closeResolution,
181 Application& app,
182 CanonicalTXSet& txns,
183 std::set<TxID>& failedTxns,
185{
186 JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close "
187 << closeTime.time_since_epoch().count()
188 << (closeTimeCorrect ? "" : " (incorrect)");
189
190 return buildLedgerImpl(
191 parent,
192 closeTime,
193 closeTimeCorrect,
194 closeResolution,
195 app,
196 j,
197 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
198 JLOG(j.debug()) << "Attempting to apply " << txns.size() << " transactions";
199
200 auto const applied = applyTransactions(app, built, txns, failedTxns, accum, j);
201
202 if (!txns.empty() || !failedTxns.empty())
203 {
204 JLOG(j.debug()) << "Applied " << applied << " transactions; " << failedTxns.size()
205 << " failed and " << txns.size() << " will be retried. "
206 << "Total transactions in ledger (including Inner Batch): "
207 << accum.txCount();
208 }
209 else
210 {
211 JLOG(j.debug()) << "Applied " << applied << " transactions. "
212 << "Total transactions in ledger (including Inner Batch): "
213 << accum.txCount();
214 }
215 });
216}
217
218// Build a ledger by replaying
221 LedgerReplay const& replayData,
222 ApplyFlags applyFlags,
223 Application& app,
225{
226 auto const& replayLedger = replayData.replay();
227
228 JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->header().hash;
229
230 return buildLedgerImpl(
231 replayData.parent(),
232 replayLedger->header().closeTime,
233 ((replayLedger->header().closeFlags & kSLcfNoConsensusTime) == 0),
234 replayLedger->header().closeTimeResolution,
235 app,
236 j,
237 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
238 for (auto& tx : replayData.orderedTxns())
239 {
240 // Inner batch transactions are applied as part of their outer
241 // Batch transaction, never on their own. Skip them here so they
242 // are not re-applied a second time outside of the batch during
243 // replay.
244 if (tx.second->isFlag(tfInnerBatchTxn))
245 continue;
246 applyTransaction(app, accum, *tx.second, false, applyFlags, j);
247 }
248 });
249}
250
251} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream debug() const
Definition Journal.h:344
Stream warn() const
Definition Journal.h:356
Holds transactions which were deferred to the next pass of consensus.
UInt256 const & key() const
const_iterator begin() const
const_iterator erase(const_iterator const &it)
const_iterator end() const
std::shared_ptr< Ledger const > const & replay() const
std::shared_ptr< Ledger const > const & parent() const
std::chrono::time_point< NetClock > time_point
Definition chrono.h:48
std::chrono::duration< rep, period > duration
Definition chrono.h:47
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:59
std::size_t txCount() const
Return the number of tx inserted since creation.
Definition OpenView.cpp:121
bool open() const override
Returns true if this reflects an open ledger.
Definition OpenView.h:187
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:127
T empty(T... args)
T insert(T... args)
T make_shared(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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.
ApplyTransactionResult applyTransaction(ServiceRegistry &registry, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition apply.cpp:267
@ Success
Applied to this ledger.
Definition apply.h:128
@ Retry
Should be retried in this ledger.
Definition apply.h:136
@ Fail
Should not be retried in this ledger.
Definition apply.h:132
static constexpr std::uint32_t kXrpLedgerEarliestFees
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
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.
ApplyFlags
Definition ApplyView.h:27
@ TapNone
Definition ApplyView.h:28
static std::uint32_t const kSLcfNoConsensusTime
FeeSettingsEntry< ReadView > FeeSettingsEntryR
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)
T size(T... args)
T time_since_epoch(T... args)
T what(T... args)