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());
154  std::make_shared<Message>(msg, protocol::mtTRANSACTION),
155  peer_in_set(*toSkip)));
156  }
157  }
158 
159  // Switch to the new open view
161  current_ = std::move(next);
162 }
163 
164 //------------------------------------------------------------------------------
165 
168  Rules const& rules,
169  std::shared_ptr<Ledger const> const& ledger)
170 {
171  return std::make_shared<OpenView>(
172  open_ledger,
173  rules,
174  std::make_shared<CachedLedger const>(ledger, cache_));
175 }
176 
177 auto
179  Application& app,
180  OpenView& view,
181  std::shared_ptr<STTx const> const& tx,
182  bool retry,
183  ApplyFlags flags,
184  bool shouldRecover,
185  beast::Journal j) -> Result
186 {
187  if (retry)
188  flags = flags | tapRETRY;
189  auto const result = [&] {
190  auto const queueResult =
191  app.getTxQ().apply(app, view, tx, flags | tapPREFER_QUEUE, j);
192  // If the transaction can't get into the queue for intrinsic
193  // reasons, and it can still be recovered, try to put it
194  // directly into the open ledger, else drop it.
195  if (queueResult.first == telCAN_NOT_QUEUE && shouldRecover)
196  return ripple::apply(app, view, *tx, flags, j);
197  return queueResult;
198  }();
199  if (result.second || result.first == terQUEUED)
200  return Result::success;
201  if (isTefFailure(result.first) || isTemMalformed(result.first) ||
202  isTelLocal(result.first))
203  return Result::failure;
204  return Result::retry;
205 }
206 
207 //------------------------------------------------------------------------------
208 
211 {
213  ss << tx->getTransactionID();
214  return ss.str().substr(0, 4);
215 }
216 
219 {
221  for (auto const& item : set)
222  ss << debugTxstr(item.second) << ", ";
223  return ss.str();
224 }
225 
228 {
230  for (auto const& item : set)
231  {
232  try
233  {
234  SerialIter sit(item.slice());
235  auto const tx = std::make_shared<STTx const>(sit);
236  ss << debugTxstr(tx) << ", ";
237  }
238  catch (std::exception const&)
239  {
240  ss << "THRO, ";
241  }
242  }
243  return ss.str();
244 }
245 
248 {
250  for (auto const& item : view->txs)
251  ss << debugTxstr(item.first) << ", ";
252  return ss.str();
253 }
254 
255 } // namespace ripple
ripple::Application
Definition: Application.h:97
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.
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:597
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
std::vector
STL class.
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:30
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::peer_in_set
Select all peers that are in the specified set.
Definition: predicates.h:160
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:36
ripple::Serializer::data
void const * data() const noexcept
Definition: Serializer.h:75
ripple::terQUEUED
@ terQUEUED
Definition: TER.h:198
std::map::emplace_hint
T emplace_hint(T... args)
ripple::CachedSLEs
Caches SLEs by their digest.
Definition: CachedSLEs.h:32
ripple::OpenLedger::j_
const beast::Journal j_
Definition: OpenLedger.h:52
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:564
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:81
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:276
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:126
ripple::SerialIter
Definition: Serializer.h:308
ripple::debugTxstr
std::string debugTxstr(std::shared_ptr< STTx const > const &tx)
Definition: OpenLedger.cpp:210
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::HashRouter::shouldRelay
boost::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
Definition: HashRouter.cpp:112
ripple::tapPREFER_QUEUE
@ tapPREFER_QUEUE
Definition: ApplyView.h:44
ripple::Overlay::foreach
void foreach(Function f) const
Visit every active peer.
Definition: Overlay.h:167
std::map
STL class.
ripple::debugTostr
std::string debugTostr(OrderedTxs const &set)
Definition: OpenLedger.cpp:218
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:131
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:39
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::send_if_not
send_if_not_pred< Predicate > send_if_not(std::shared_ptr< Message > const &m, Predicate const &f)
Helper function to aid in type deduction.
Definition: predicates.h:107
ripple::OpenLedger::cache_
CachedSLEs & cache_
Definition: OpenLedger.h:53
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:552
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:127
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:167
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:178
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:558
ripple::ReadView::txs
txs_type txs
Definition: ReadView.h:386