rippled
Loading...
Searching...
No Matches
BuildLedger.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2018 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/ledger/BuildLedger.h>
21#include <xrpld/app/ledger/Ledger.h>
22#include <xrpld/app/ledger/LedgerReplay.h>
23#include <xrpld/app/ledger/OpenLedger.h>
24#include <xrpld/app/misc/CanonicalTXSet.h>
25#include <xrpld/app/tx/apply.h>
26#include <xrpl/protocol/Feature.h>
27
28namespace ripple {
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>
40 NetClock::time_point closeTime,
41 const bool 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() && built->rules().enabled(featureNegativeUNL))
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(
60 !accum.open(), "ripple::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(hotACCOUNT_NODE);
71 int const tmf = built->txMap().flushDirty(hotTRANSACTION_NODE);
72 JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf
73 << " transaction nodes";
74 }
75 built->unshare();
76
77 // Accept ledger
78 XRPL_ASSERT(
79 built->info().seq < XRP_LEDGER_EARLIEST_FEES ||
80 built->read(keylet::fees()),
81 "ripple::buildLedgerImpl : valid ledger fees");
82 built->setAccepted(closeTime, closeResolution, closeTimeCorrect);
83
84 return built;
85}
86
99 Application& app,
101 CanonicalTXSet& txns,
102 std::set<TxID>& failed,
103 OpenView& view,
105{
106 bool certainRetry = true;
107 std::size_t count = 0;
108
109 // Attempt to apply all of the retriable transactions
110 for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
111 {
112 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
113 << " begins (" << txns.size() << " transactions)";
114 int changes = 0;
115
116 auto it = txns.begin();
117
118 while (it != txns.end())
119 {
120 auto const txid = it->first.getTXID();
121
122 try
123 {
124 if (pass == 0 && built->txExists(txid))
125 {
126 it = txns.erase(it);
127 continue;
128 }
129
130 switch (applyTransaction(
131 app, view, *it->second, certainRetry, tapNONE, j))
132 {
134 it = txns.erase(it);
135 ++changes;
136 break;
137
139 failed.insert(txid);
140 it = txns.erase(it);
141 break;
142
144 ++it;
145 }
146 }
147 catch (std::exception const& ex)
148 {
149 JLOG(j.warn())
150 << "Transaction " << txid << " throws: " << ex.what();
151 failed.insert(txid);
152 it = txns.erase(it);
153 }
154 }
155
156 JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
157 << " completed (" << changes << " changes)";
158
159 // Accumulate changes.
160 count += changes;
161
162 // A non-retry pass made no changes
163 if (!changes && !certainRetry)
164 break;
165
166 // Stop retriable passes
167 if (!changes || (pass >= LEDGER_RETRY_PASSES))
168 certainRetry = false;
169 }
170
171 // If there are any transactions left, we must have
172 // tried them in at least one final pass
173 XRPL_ASSERT(
174 txns.empty() || !certainRetry,
175 "ripple::applyTransactions : retry transactions");
176 return count;
177}
178
179// Build a ledger from consensus transactions
182 std::shared_ptr<Ledger const> const& parent,
183 NetClock::time_point closeTime,
184 const bool closeTimeCorrect,
185 NetClock::duration closeResolution,
186 Application& app,
187 CanonicalTXSet& txns,
188 std::set<TxID>& failedTxns,
190{
191 JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close "
192 << closeTime.time_since_epoch().count()
193 << (closeTimeCorrect ? "" : " (incorrect)");
194
195 return buildLedgerImpl(
196 parent,
197 closeTime,
198 closeTimeCorrect,
199 closeResolution,
200 app,
201 j,
202 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
203 JLOG(j.debug())
204 << "Attempting to apply " << txns.size() << " transactions";
205
206 auto const applied =
207 applyTransactions(app, built, txns, failedTxns, accum, j);
208
209 if (!txns.empty() || !failedTxns.empty())
210 JLOG(j.debug()) << "Applied " << applied << " transactions; "
211 << failedTxns.size() << " failed and "
212 << txns.size() << " will be retried.";
213 else
214 JLOG(j.debug()) << "Applied " << applied << " transactions.";
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->info().hash;
229
230 return buildLedgerImpl(
231 replayData.parent(),
232 replayLedger->info().closeTime,
233 ((replayLedger->info().closeFlags & sLCF_NoConsensusTime) == 0),
234 replayLedger->info().closeTimeResolution,
235 app,
236 j,
237 [&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
238 for (auto& tx : replayData.orderedTxns())
239 applyTransaction(app, accum, *tx.second, false, applyFlags, j);
240 });
241}
242
243} // namespace ripple
A generic endpoint for log messages.
Definition: Journal.h:60
Stream debug() const
Definition: Journal.h:328
Stream warn() const
Definition: Journal.h:340
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
Definition: LedgerReplay.h:52
std::shared_ptr< Ledger const > const & replay() const
Definition: LedgerReplay.h:60
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:56
bool open() const override
Returns true if this reflects an open ledger.
Definition: OpenView.h:175
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:130
T empty(T... args)
T insert(T... args)
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:213
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::shared_ptr< Ledger > buildLedger(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, const bool closeTimeCorrect, NetClock::duration closeResolution, Application &app, CanonicalTXSet &txns, std::set< TxID > &failedTxs, beast::Journal j)
Build a new ledger by applying consensus transactions.
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.
Definition: BuildLedger.cpp:98
@ 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:35
@ hotTRANSACTION_NODE
Definition: NodeObject.h:36
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
std::shared_ptr< Ledger > buildLedgerImpl(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, const bool closeTimeCorrect, NetClock::duration closeResolution, Application &app, beast::Journal j, ApplyTxs &&applyTxs)
Definition: BuildLedger.cpp:38
static std::uint32_t const sLCF_NoConsensusTime
Definition: LedgerHeader.h:82
ApplyFlags
Definition: ApplyView.h:30
@ tapNONE
Definition: ApplyView.h:31
ApplyTransactionResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:125
T size(T... args)
T time_since_epoch(T... args)
T what(T... args)