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