rippled
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 <ripple/app/ledger/BuildLedger.h>
21 #include <ripple/app/ledger/Ledger.h>
22 #include <ripple/app/ledger/LedgerReplay.h>
23 #include <ripple/app/ledger/OpenLedger.h>
24 #include <ripple/app/main/Application.h>
25 #include <ripple/app/misc/CanonicalTXSet.h>
26 #include <ripple/app/tx/apply.h>
27 #include <ripple/protocol/Feature.h>
28 
29 namespace ripple {
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 */
37 template <class ApplyTxs>
40  std::shared_ptr<Ledger const> const& parent,
41  NetClock::time_point closeTime,
42  const bool closeTimeCorrect,
43  NetClock::duration closeResolution,
44  Application& app,
46  ApplyTxs&& applyTxs)
47 {
48  auto built = std::make_shared<Ledger>(*parent, closeTime);
49 
50  // Set up to write SHAMap changes to our database,
51  // perform updates, extract changes
52 
53  {
54  OpenView accum(&*built);
55  assert(!accum.open());
56  applyTxs(accum, built);
57  accum.apply(*built);
58  }
59 
60  built->updateSkipList();
61  {
62  // Write the final version of all modified SHAMap
63  // nodes to the node store to preserve the new LCL
64 
65  int const asf = built->stateMap().flushDirty(
66  hotACCOUNT_NODE, built->info().seq);
67  int const tmf = built->txMap().flushDirty(
68  hotTRANSACTION_NODE, built->info().seq);
69  JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf
70  << " transaction nodes";
71  }
72  built->unshare();
73 
74  // Accept ledger
75  built->setAccepted(
76  closeTime, closeResolution, closeTimeCorrect, app.config());
77 
78  return built;
79 }
80 
93  Application& app,
94  std::shared_ptr<Ledger const> const& built,
95  CanonicalTXSet& txns,
96  std::set<TxID>& failed,
97  OpenView& view,
99 {
100  bool certainRetry = true;
101  std::size_t count = 0;
102 
103  // Attempt to apply all of the retriable transactions
104  for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
105  {
106  JLOG(j.debug())
107  << (certainRetry ? "Pass: " : "Final pass: ") << pass
108  << " begins (" << txns.size() << " transactions)";
109  int changes = 0;
110 
111  auto it = txns.begin();
112 
113  while (it != txns.end())
114  {
115  auto const txid = it->first.getTXID();
116 
117  try
118  {
119  if (pass == 0 && built->txExists(txid))
120  {
121  it = txns.erase(it);
122  continue;
123  }
124 
125  switch (applyTransaction(
126  app, view, *it->second, certainRetry, tapNONE, j))
127  {
129  it = txns.erase(it);
130  ++changes;
131  break;
132 
133  case ApplyResult::Fail:
134  failed.insert(txid);
135  it = txns.erase(it);
136  break;
137 
138  case ApplyResult::Retry:
139  ++it;
140  }
141  }
142  catch (std::exception const&)
143  {
144  JLOG(j.warn()) << "Transaction " << txid << " throws";
145  failed.insert(txid);
146  it = txns.erase(it);
147  }
148  }
149 
150  JLOG(j.debug())
151  << (certainRetry ? "Pass: " : "Final pass: ") << pass
152  << " completed (" << changes << " changes)";
153 
154  // Accumulate changes.
155  count += changes;
156 
157  // A non-retry pass made no changes
158  if (!changes && !certainRetry)
159  break;
160 
161  // Stop retriable passes
162  if (!changes || (pass >= LEDGER_RETRY_PASSES))
163  certainRetry = false;
164  }
165 
166  // If there are any transactions left, we must have
167  // tried them in at least one final pass
168  assert(txns.empty() || !certainRetry);
169  return count;
170 }
171 
172 // Build a ledger from consensus transactions
175  std::shared_ptr<Ledger const> const& parent,
176  NetClock::time_point closeTime,
177  const bool closeTimeCorrect,
178  NetClock::duration closeResolution,
179  Application& app,
180  CanonicalTXSet& txns,
181  std::set<TxID>& failedTxns,
182  beast::Journal j)
183 {
184  JLOG(j.debug()) << "Report: Transaction Set = " << txns.key()
185  << ", close " << closeTime.time_since_epoch().count()
186  << (closeTimeCorrect ? "" : " (incorrect)");
187 
188  return buildLedgerImpl(parent, closeTime, closeTimeCorrect,
189  closeResolution, app, j,
190  [&](OpenView& accum, std::shared_ptr<Ledger> const& built)
191  {
192  JLOG(j.debug())
193  << "Attempting to apply " << txns.size()
194  << " transactions";
195 
196  auto const applied = applyTransactions(app, built, txns,
197  failedTxns, accum, j);
198 
199  if (!txns.empty() || !failedTxns.empty())
200  JLOG(j.debug())
201  << "Applied " << applied << " transactions; "
202  << failedTxns.size() << " failed and "
203  << txns.size() << " will be retried.";
204  else
205  JLOG(j.debug())
206  << "Applied " << applied
207  << " transactions.";
208  });
209 }
210 
211 // Build a ledger by replaying
214  LedgerReplay const& replayData,
215  ApplyFlags applyFlags,
216  Application& app,
217  beast::Journal j)
218 {
219  auto const& replayLedger = replayData.replay();
220 
221  JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->info().hash;
222 
223  return buildLedgerImpl(
224  replayData.parent(),
225  replayLedger->info().closeTime,
226  ((replayLedger->info().closeFlags & sLCF_NoConsensusTime) == 0),
227  replayLedger->info().closeTimeResolution,
228  app,
229  j,
230  [&](OpenView& accum, std::shared_ptr<Ledger> const& built)
231  {
232  for (auto& tx : replayData.orderedTxns())
233  applyTransaction(app, accum, *tx.second, false, applyFlags, j);
234  });
235 }
236 
237 } // namespace ripple
ripple::Application
Definition: Application.h:85
std::shared_ptr
STL class.
std::exception
STL class.
ripple::CanonicalTXSet::key
uint256 const & key() const
Definition: CanonicalTXSet.h:122
ripple::OpenView::apply
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:120
ripple::CanonicalTXSet::erase
const_iterator erase(const_iterator const &it)
Definition: CanonicalTXSet.h:98
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:37
ripple::applyTransaction
ApplyResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:118
std::set::size
T size(T... args)
std::chrono::duration
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:30
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::hotTRANSACTION_NODE
@ hotTRANSACTION_NODE
Definition: NodeObject.h:38
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:33
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:36
ripple::CanonicalTXSet::begin
const_iterator begin() const
Definition: CanonicalTXSet.h:103
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::LedgerReplay::parent
std::shared_ptr< Ledger const > const & parent() const
Definition: LedgerReplay.h:46
ripple::Ledger::txExists
bool txExists(uint256 const &key) const override
Returns true if a tx exists in the tx map.
Definition: Ledger.cpp:477
ripple::buildLedgerImpl
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:39
ripple::Application::config
virtual Config & config()=0
ripple::ApplyResult::Retry
@ Retry
Should be retried in this ledger.
ripple::OpenView::open
bool open() const override
Returns true if this reflects an open ledger.
Definition: OpenView.h:144
std::chrono::time_point
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
ripple::LedgerReplay::replay
std::shared_ptr< Ledger const > const & replay() const
Definition: LedgerReplay.h:54
ripple::applyTransactions
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:92
ripple::ApplyResult::Success
@ Success
Applied to this ledger.
ripple::CanonicalTXSet::end
const_iterator end() const
Definition: CanonicalTXSet.h:108
ripple::ApplyResult::Fail
@ Fail
Should not be retried in this ledger.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::CanonicalTXSet::size
size_t size() const
Definition: CanonicalTXSet.h:113
std::set::insert
T insert(T... args)
ripple::CanonicalTXSet::empty
bool empty() const
Definition: CanonicalTXSet.h:117
ripple::buildLedger
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.
Definition: BuildLedger.cpp:174
std::set::empty
T empty(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
std::size_t
std::set
STL class.
ripple::sLCF_NoConsensusTime
static const std::uint32_t sLCF_NoConsensusTime
Definition: ReadView.h:429
ripple::LedgerReplay
Definition: LedgerReplay.h:32