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/nodestore/NodeObject.h>
16#include <xrpl/protocol/Indexes.h> // IWYU pragma: keep
17#include <xrpl/protocol/LedgerHeader.h>
18#include <xrpl/protocol/Protocol.h>
19#include <xrpl/protocol/SystemParameters.h> // IWYU pragma: keep
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/tx/apply.h>
22
23#include <cstddef>
24#include <exception>
25#include <memory>
26#include <set>
27
28namespace xrpl {
29
30/* Generic buildLedgerImpl that dispatches to ApplyTxs invocable with signature
31 void(OpenView&, std::shared_ptr<Ledger> const&)
32 It is responsible for adding transactions to the open view to generate the
33 new ledger. It is generic since the mechanics differ for consensus
34 generated ledgers versus replayed ledgers.
35*/
36template <class ApplyTxs>
37std::shared_ptr<Ledger>
40 NetClock::time_point closeTime,
41 bool const closeTimeCorrect,
42 NetClock::duration closeResolution,
43 Application& app,
45 ApplyTxs&& applyTxs)
46{
47 auto built = std::make_shared<Ledger>(*parent, closeTime);
48
49 if (built->isFlagLedger())
50 {
51 built->updateNegativeUNL();
52 }
53
54 // Set up to write SHAMap changes to our database,
55 // perform updates, extract changes
56
57 {
58 OpenView accum(&*built);
59 XRPL_ASSERT(!accum.open(), "xrpl::buildLedgerImpl : valid ledger state");
60 applyTxs(accum, built);
61 accum.apply(*built);
62 }
63
64 built->updateSkipList();
65 {
66 // Write the final version of all modified SHAMap
67 // nodes to the node store to preserve the new LCL
68
69 int const asf = built->stateMap().flushDirty(NodeObjectType::AccountNode);
70 int const tmf = built->txMap().flushDirty(NodeObjectType::TransactionNode);
71 JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf << " transaction nodes";
72 }
73 built->unshare();
74
75 // Accept ledger
76 XRPL_ASSERT(
77 built->header().seq < kXrpLedgerEarliestFees || built->read(keylet::feeSettings()),
78 "xrpl::buildLedgerImpl : valid ledger fees");
79 built->setAccepted(closeTime, closeResolution, closeTimeCorrect);
80
81 return built;
82}
83
94
97 Application& app,
99 CanonicalTXSet& txns,
100 std::set<TxID>& failed,
101 OpenView& view,
103{
104 bool certainRetry = true;
105 std::size_t count = 0;
106
107 // Attempt to apply all of the retriable transactions
108 for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
109 {
110 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " begins ("
111 << txns.size() << " transactions)";
112 int changes = 0;
113
114 auto it = txns.begin();
115
116 while (it != txns.end())
117 {
118 auto const txid = it->first.getTXID();
119
120 try
121 {
122 if (pass == 0 && built->txExists(txid))
123 {
124 it = txns.erase(it);
125 continue;
126 }
127
128 switch (applyTransaction(app, view, *it->second, certainRetry, TapNone, j))
129 {
131 it = txns.erase(it);
132 ++changes;
133 break;
134
136 failed.insert(txid);
137 it = txns.erase(it);
138 break;
139
141 ++it;
142 }
143 }
144 catch (std::exception const& ex)
145 {
146 JLOG(j.warn()) << "Transaction " << txid << " throws: " << ex.what();
147 failed.insert(txid);
148 it = txns.erase(it);
149 }
150 }
151
152 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " completed ("
153 << changes << " changes)";
154
155 // Accumulate changes.
156 count += changes;
157
158 // A non-retry pass made no changes
159 if ((changes == 0) && !certainRetry)
160 break;
161
162 // Stop retriable passes
163 if ((changes == 0) || (pass >= LEDGER_RETRY_PASSES))
164 certainRetry = false;
165 }
166
167 // If there are any transactions left, we must have
168 // tried them in at least one final pass
169 XRPL_ASSERT(txns.empty() || !certainRetry, "xrpl::applyTransactions : retry transactions");
170 return count;
171}
172
173// Build a ledger from consensus transactions
176 std::shared_ptr<Ledger const> const& parent,
177 NetClock::time_point closeTime,
178 bool const closeTimeCorrect,
179 NetClock::duration closeResolution,
180 Application& app,
181 CanonicalTXSet& txns,
182 std::set<TxID>& failedTxns,
184{
185 JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close "
186 << closeTime.time_since_epoch().count()
187 << (closeTimeCorrect ? "" : " (incorrect)");
188
189 return buildLedgerImpl(
190 parent,
191 closeTime,
192 closeTimeCorrect,
193 closeResolution,
194 app,
195 j,
196 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
197 JLOG(j.debug()) << "Attempting to apply " << txns.size() << " transactions";
198
199 auto const applied = applyTransactions(app, built, txns, failedTxns, accum, j);
200
201 if (!txns.empty() || !failedTxns.empty())
202 {
203 JLOG(j.debug()) << "Applied " << applied << " transactions; " << failedTxns.size()
204 << " failed and " << txns.size() << " will be retried. "
205 << "Total transactions in ledger (including Inner Batch): "
206 << accum.txCount();
207 }
208 else
209 {
210 JLOG(j.debug()) << "Applied " << applied << " transactions. "
211 << "Total transactions in ledger (including Inner Batch): "
212 << accum.txCount();
213 }
214 });
215}
216
217// Build a ledger by replaying
220 LedgerReplay const& replayData,
221 ApplyFlags applyFlags,
222 Application& app,
224{
225 auto const& replayLedger = replayData.replay();
226
227 JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->header().hash;
228
229 return buildLedgerImpl(
230 replayData.parent(),
231 replayLedger->header().closeTime,
232 ((replayLedger->header().closeFlags & kSLcfNoConsensusTime) == 0),
233 replayLedger->header().closeTimeResolution,
234 app,
235 j,
236 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
237 for (auto& tx : replayData.orderedTxns())
238 {
239 // Inner batch transactions are applied as part of their outer
240 // Batch transaction, never on their own. Skip them here so they
241 // are not re-applied a second time outside of the batch during
242 // replay.
243 if (tx.second->isFlag(tfInnerBatchTxn))
244 continue;
245 applyTransaction(app, accum, *tx.second, false, applyFlags, j);
246 }
247 });
248}
249
250} // 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.
const_iterator begin() const
const_iterator erase(const_iterator const &it)
const_iterator end() const
uint256 const & key() 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:120
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:126
T empty(T... args)
T insert(T... args)
T make_shared(T... args)
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:233
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:208
@ 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
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)