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 xrpl {
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(!accum.open(), "xrpl::buildLedgerImpl : valid ledger state");
42 applyTxs(accum, built);
43 accum.apply(*built);
44 }
45
46 built->updateSkipList();
47 {
48 // Write the final version of all modified SHAMap
49 // nodes to the node store to preserve the new LCL
50
51 int const asf = built->stateMap().flushDirty(hotACCOUNT_NODE);
52 int const tmf = built->txMap().flushDirty(hotTRANSACTION_NODE);
53 JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf << " transaction nodes";
54 }
55 built->unshare();
56
57 // Accept ledger
58 XRPL_ASSERT(
59 built->header().seq < XRP_LEDGER_EARLIEST_FEES || built->read(keylet::fees()),
60 "xrpl::buildLedgerImpl : valid ledger fees");
61 built->setAccepted(closeTime, closeResolution, closeTimeCorrect);
62
63 return built;
64}
65
78 Application& app,
80 CanonicalTXSet& txns,
81 std::set<TxID>& failed,
82 OpenView& view,
84{
85 bool certainRetry = true;
86 std::size_t count = 0;
87
88 // Attempt to apply all of the retriable transactions
89 for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
90 {
91 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " begins (" << txns.size()
92 << " transactions)";
93 int changes = 0;
94
95 auto it = txns.begin();
96
97 while (it != txns.end())
98 {
99 auto const txid = it->first.getTXID();
100
101 try
102 {
103 if (pass == 0 && built->txExists(txid))
104 {
105 it = txns.erase(it);
106 continue;
107 }
108
109 switch (applyTransaction(app, view, *it->second, certainRetry, tapNONE, j))
110 {
112 it = txns.erase(it);
113 ++changes;
114 break;
115
117 failed.insert(txid);
118 it = txns.erase(it);
119 break;
120
122 ++it;
123 }
124 }
125 catch (std::exception const& ex)
126 {
127 JLOG(j.warn()) << "Transaction " << txid << " throws: " << ex.what();
128 failed.insert(txid);
129 it = txns.erase(it);
130 }
131 }
132
133 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " completed (" << changes
134 << " changes)";
135
136 // Accumulate changes.
137 count += changes;
138
139 // A non-retry pass made no changes
140 if (!changes && !certainRetry)
141 break;
142
143 // Stop retriable passes
144 if (!changes || (pass >= LEDGER_RETRY_PASSES))
145 certainRetry = false;
146 }
147
148 // If there are any transactions left, we must have
149 // tried them in at least one final pass
150 XRPL_ASSERT(txns.empty() || !certainRetry, "xrpl::applyTransactions : retry transactions");
151 return count;
152}
153
154// Build a ledger from consensus transactions
157 std::shared_ptr<Ledger const> const& parent,
158 NetClock::time_point closeTime,
159 bool const closeTimeCorrect,
160 NetClock::duration closeResolution,
161 Application& app,
162 CanonicalTXSet& txns,
163 std::set<TxID>& failedTxns,
165{
166 JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close " << closeTime.time_since_epoch().count()
167 << (closeTimeCorrect ? "" : " (incorrect)");
168
169 return buildLedgerImpl(
170 parent,
171 closeTime,
172 closeTimeCorrect,
173 closeResolution,
174 app,
175 j,
176 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
177 JLOG(j.debug()) << "Attempting to apply " << txns.size() << " transactions";
178
179 auto const applied = applyTransactions(app, built, txns, failedTxns, accum, j);
180
181 if (!txns.empty() || !failedTxns.empty())
182 JLOG(j.debug()) << "Applied " << applied << " transactions; " << failedTxns.size() << " failed and "
183 << txns.size() << " will be retried. "
184 << "Total transactions in ledger (including Inner Batch): " << accum.txCount();
185 else
186 JLOG(j.debug()) << "Applied " << applied << " transactions. "
187 << "Total transactions in ledger (including Inner Batch): " << accum.txCount();
188 });
189}
190
191// Build a ledger by replaying
193buildLedger(LedgerReplay const& replayData, ApplyFlags applyFlags, Application& app, beast::Journal j)
194{
195 auto const& replayLedger = replayData.replay();
196
197 JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->header().hash;
198
199 return buildLedgerImpl(
200 replayData.parent(),
201 replayLedger->header().closeTime,
202 ((replayLedger->header().closeFlags & sLCF_NoConsensusTime) == 0),
203 replayLedger->header().closeTimeResolution,
204 app,
205 j,
206 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
207 for (auto& tx : replayData.orderedTxns())
208 applyTransaction(app, accum, *tx.second, false, applyFlags, j);
209 });
210}
211
212} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream debug() const
Definition Journal.h:300
Stream warn() const
Definition Journal.h:312
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
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:95
bool open() const override
Returns true if this reflects an open ledger.
Definition OpenView.h:160
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:101
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:194
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
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(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition apply.cpp:190
@ Success
Applied to this ledger.
@ Retry
Should be retried in this ledger.
@ Fail
Should not be retried in this ledger.
@ hotTRANSACTION_NODE
Definition NodeObject.h:16
@ hotACCOUNT_NODE
Definition NodeObject.h:15
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.
ApplyFlags
Definition ApplyView.h:10
@ tapNONE
Definition ApplyView.h:11
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)