rippled
OpenLedger.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/OpenLedger.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/HashRouter.h>
23 #include <ripple/app/misc/TxQ.h>
24 #include <ripple/app/tx/apply.h>
25 #include <ripple/ledger/CachedView.h>
26 #include <ripple/overlay/Message.h>
27 #include <ripple/overlay/Overlay.h>
28 #include <ripple/overlay/predicates.h>
29 #include <ripple/protocol/Feature.h>
30 #include <boost/range/adaptor/transformed.hpp>
31 
32 namespace ripple {
33 
35  std::shared_ptr<Ledger const> const& ledger,
36  CachedSLEs& cache,
37  beast::Journal journal)
38  : j_(journal), cache_(cache), current_(create(ledger->rules(), ledger))
39 {
40 }
41 
42 bool
44 {
46  return current_->txCount() == 0;
47 }
48 
51 {
53  return current_;
54 }
55 
56 bool
58 {
60  auto next = std::make_shared<OpenView>(*current_);
61  auto const changed = f(*next, j_);
62  if (changed)
63  {
65  current_ = std::move(next);
66  }
67  return changed;
68 }
69 
70 void
72  Application& app,
73  Rules const& rules,
74  std::shared_ptr<Ledger const> const& ledger,
75  OrderedTxs const& locals,
76  bool retriesFirst,
77  OrderedTxs& retries,
78  ApplyFlags flags,
79  std::string const& suffix,
80  modify_type const& f)
81 {
82  JLOG(j_.trace()) << "accept ledger " << ledger->seq() << " " << suffix;
83  auto next = create(rules, ledger);
84  std::map<uint256, bool> shouldRecover;
85  if (retriesFirst)
86  {
87  for (auto const& tx : retries)
88  {
89  auto const txID = tx.second->getTransactionID();
90  shouldRecover[txID] = app.getHashRouter().shouldRecover(txID);
91  }
92  // Handle disputed tx, outside lock
94  apply(app, *next, *ledger, empty{}, retries, flags, shouldRecover, j_);
95  }
96  // Block calls to modify, otherwise
97  // new tx going into the open ledger
98  // would get lost.
100  // Apply tx from the current open view
101  if (!current_->txs.empty())
102  {
103  for (auto const& tx : current_->txs)
104  {
105  auto const txID = tx.first->getTransactionID();
106  auto iter = shouldRecover.lower_bound(txID);
107  if (iter != shouldRecover.end() && iter->first == txID)
108  // already had a chance via disputes
109  iter->second = false;
110  else
111  shouldRecover.emplace_hint(
112  iter, txID, app.getHashRouter().shouldRecover(txID));
113  }
114  apply(
115  app,
116  *next,
117  *ledger,
118  boost::adaptors::transform(
119  current_->txs,
120  [](std::pair<
123  return p.first;
124  }),
125  retries,
126  flags,
127  shouldRecover,
128  j_);
129  }
130  // Call the modifier
131  if (f)
132  f(*next, j_);
133  // Apply local tx
134  for (auto const& item : locals)
135  app.getTxQ().apply(app, *next, item.second, flags, j_);
136 
137  // If we didn't relay this transaction recently, relay it to all peers
138  for (auto const& txpair : next->txs)
139  {
140  auto const& tx = txpair.first;
141  auto const txId = tx->getTransactionID();
142  if (auto const toSkip = app.getHashRouter().shouldRelay(txId))
143  {
144  JLOG(j_.debug()) << "Relaying recovered tx " << txId;
145  protocol::TMTransaction msg;
146  Serializer s;
147 
148  tx->add(s);
149  msg.set_rawtransaction(s.data(), s.size());
150  msg.set_status(protocol::tsNEW);
151  msg.set_receivetimestamp(
152  app.timeKeeper().now().time_since_epoch().count());
153  app.overlay().relay(txId, msg, *toSkip);
154  }
155  }
156 
157  // Switch to the new open view
159  current_ = std::move(next);
160 }
161 
162 //------------------------------------------------------------------------------
163 
166  Rules const& rules,
167  std::shared_ptr<Ledger const> const& ledger)
168 {
169  return std::make_shared<OpenView>(
170  open_ledger,
171  rules,
172  std::make_shared<CachedLedger const>(ledger, cache_));
173 }
174 
175 auto
177  Application& app,
178  OpenView& view,
179  std::shared_ptr<STTx const> const& tx,
180  bool retry,
181  ApplyFlags flags,
182  bool shouldRecover,
183  beast::Journal j) -> Result
184 {
185  if (retry)
186  flags = flags | tapRETRY;
187  auto const result = [&] {
188  auto const queueResult =
189  app.getTxQ().apply(app, view, tx, flags | tapPREFER_QUEUE, j);
190  // If the transaction can't get into the queue for intrinsic
191  // reasons, and it can still be recovered, try to put it
192  // directly into the open ledger, else drop it.
193  if (queueResult.first == telCAN_NOT_QUEUE && shouldRecover)
194  return ripple::apply(app, view, *tx, flags, j);
195  return queueResult;
196  }();
197  if (result.second || result.first == terQUEUED)
198  return Result::success;
199  if (isTefFailure(result.first) || isTemMalformed(result.first) ||
200  isTelLocal(result.first))
201  return Result::failure;
202  return Result::retry;
203 }
204 
205 //------------------------------------------------------------------------------
206 
209 {
211  ss << tx->getTransactionID();
212  return ss.str().substr(0, 4);
213 }
214 
217 {
219  for (auto const& item : set)
220  ss << debugTxstr(item.second) << ", ";
221  return ss.str();
222 }
223 
226 {
228  for (auto const& item : set)
229  {
230  try
231  {
232  SerialIter sit(item.slice());
233  auto const tx = std::make_shared<STTx const>(sit);
234  ss << debugTxstr(tx) << ", ";
235  }
236  catch (std::exception const&)
237  {
238  ss << "THRO, ";
239  }
240  }
241  return ss.str();
242 }
243 
246 {
248  for (auto const& item : view->txs)
249  ss << debugTxstr(item.first) << ", ";
250  return ss.str();
251 }
252 
253 } // namespace ripple
ripple::Application
Definition: Application.h:115
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
std::string
STL class.
std::shared_ptr
STL class.
ripple::TaggedCache< uint256, SLE const >
std::exception
STL class.
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::OpenLedger::current_
std::shared_ptr< OpenView const > current_
Definition: OpenLedger.h:56
ripple::apply
std::pair< TER, bool > apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition: apply.cpp:109
ripple::open_ledger
const open_ledger_t open_ledger
Definition: OpenView.cpp:25
std::pair
ripple::TxQ::apply
std::pair< TER, bool > apply(Application &app, OpenView &view, std::shared_ptr< STTx const > const &tx, ApplyFlags flags, beast::Journal j)
Add a new transaction to the open ledger, hold it in the queue, or reject it.
Definition: TxQ.cpp:725
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
std::vector
STL class.
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:29
std::stringstream
STL class.
std::lock_guard
STL class.
ripple::telCAN_NOT_QUEUE
@ telCAN_NOT_QUEUE
Definition: TER.h:58
std::function
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::OpenLedger::modify_mutex_
std::mutex modify_mutex_
Definition: OpenLedger.h:54
ripple::OpenLedger::accept
void accept(Application &app, Rules const &rules, std::shared_ptr< Ledger const > const &ledger, OrderedTxs const &locals, bool retriesFirst, OrderedTxs &retries, ApplyFlags flags, std::string const &suffix="", modify_type const &f={})
Accept a new ledger.
Definition: OpenLedger.cpp:71
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:37
ripple::Serializer::data
void const * data() const noexcept
Definition: Serializer.h:75
ripple::terQUEUED
@ terQUEUED
Definition: TER.h:201
std::map::emplace_hint
T emplace_hint(T... args)
ripple::OpenLedger::j_
const beast::Journal j_
Definition: OpenLedger.h:52
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:572
ripple::OpenLedger::OpenLedger
OpenLedger()=delete
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:95
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:313
ripple::HashRouter::shouldRecover
bool shouldRecover(uint256 const &key)
Determines whether the hashed item should be recovered from the open ledger into the next open ledger...
Definition: HashRouter.cpp:132
ripple::SerialIter
Definition: Serializer.h:310
ripple::debugTxstr
std::string debugTxstr(std::shared_ptr< STTx const > const &tx)
Definition: OpenLedger.cpp:208
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Overlay::relay
virtual std::set< Peer::id_t > relay(protocol::TMProposeSet &m, uint256 const &uid, PublicKey const &validator)=0
Relay a proposal.
ripple::HashRouter::shouldRelay
std::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
Definition: HashRouter.cpp:118
ripple::tapPREFER_QUEUE
@ tapPREFER_QUEUE
Definition: ApplyView.h:43
std::map
STL class.
ripple::debugTostr
std::string debugTostr(OrderedTxs const &set)
Definition: OpenLedger.cpp:216
ripple::OpenLedger::empty
bool empty() const
Returns true if there are no transactions.
Definition: OpenLedger.cpp:43
ripple::STTx::getTransactionID
uint256 getTransactionID() const
Definition: STTx.h:118
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:38
ripple::Serializer
Definition: Serializer.h:39
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::map::lower_bound
T lower_bound(T... args)
ripple::Serializer::size
std::size_t size() const noexcept
Definition: Serializer.h:69
ripple::OpenLedger::cache_
CachedSLEs & cache_
Definition: OpenLedger.h:53
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:560
ripple::TimeKeeper::now
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
ripple::Application::overlay
virtual Overlay & overlay()=0
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:131
std::stringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::OpenLedger::Result
Result
Definition: OpenLedger.h:191
std::map::end
T end(T... args)
ripple::OpenLedger::create
std::shared_ptr< OpenView > create(Rules const &rules, std::shared_ptr< Ledger const > const &ledger)
Definition: OpenLedger.cpp:165
ripple::OpenLedger::current_mutex_
std::mutex current_mutex_
Definition: OpenLedger.h:55
ripple::OpenLedger::apply_one
static Result apply_one(Application &app, OpenView &view, std::shared_ptr< STTx const > const &tx, bool retry, ApplyFlags flags, bool shouldRecover, beast::Journal j)
Definition: OpenLedger.cpp:176
ripple::OpenLedger::apply
static void apply(Application &app, OpenView &view, ReadView const &check, FwdRange const &txs, OrderedTxs &retries, ApplyFlags flags, std::map< uint256, bool > &shouldRecover, beast::Journal j)
Algorithm for applying transactions.
Definition: OpenLedger.h:211
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:57
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:566
ripple::ReadView::txs
txs_type txs
Definition: ReadView.h:390