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  Ledger const> const& ledger,
36  CachedSLEs& cache,
37  beast::Journal journal)
38  : j_ (journal)
39  , cache_ (cache)
40  , current_ (create(ledger->rules(), ledger))
41 {
42 }
43 
44 bool
46 {
48  return current_->txCount() == 0;
49 }
50 
53 {
55  return current_;
56 }
57 
58 bool
60 {
62  auto next = std::make_shared<
63  OpenView>(*current_);
64  auto const changed = f(*next, j_);
65  if (changed)
66  {
68  current_ = std::move(next);
69  }
70  return changed;
71 }
72 
73 void
75  std::shared_ptr<Ledger const> const& ledger,
76  OrderedTxs const& locals, bool retriesFirst,
77  OrderedTxs& retries, ApplyFlags flags,
78  std::string const& suffix,
79  modify_type const& f)
80 {
81  JLOG(j_.trace()) <<
82  "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
93  using empty =
95  STTx const>>;
96  apply (app, *next, *ledger, empty{},
97  retries, flags, shouldRecover, j_);
98  }
99  // Block calls to modify, otherwise
100  // new tx going into the open ledger
101  // would get lost.
103  // Apply tx from the current open view
104  if (! current_->txs.empty())
105  {
106  for (auto const& tx : current_->txs)
107  {
108  auto const txID = tx.first->getTransactionID();
109  auto iter = shouldRecover.lower_bound(txID);
110  if (iter != shouldRecover.end()
111  && iter->first == txID)
112  // already had a chance via disputes
113  iter->second = false;
114  else
115  shouldRecover.emplace_hint(iter, txID,
116  app.getHashRouter().shouldRecover(txID));
117  }
118  apply (app, *next, *ledger,
119  boost::adaptors::transform(
120  current_->txs,
122  STTx const>, std::shared_ptr<
123  STObject const>> const& p)
124  {
125  return p.first;
126  }),
127  retries, flags, shouldRecover, j_);
128  }
129  // Call the modifier
130  if (f)
131  f(*next, j_);
132  // Apply local tx
133  for (auto const& item : locals)
134  app.getTxQ().apply(app, *next,
135  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 
167 OpenLedger::create (Rules const& rules,
168  std::shared_ptr<Ledger const> const& ledger)
169 {
170  return std::make_shared<OpenView>(
172  CachedLedger const>(ledger,
173  cache_));
174 }
175 
176 auto
178  std::shared_ptr<STTx const> const& tx,
179  bool retry, ApplyFlags flags, bool shouldRecover,
180  beast::Journal j) -> Result
181 {
182  if (retry)
183  flags = flags | tapRETRY;
184  auto const result = [&]
185  {
186  auto const queueResult = app.getTxQ().apply(
187  app, view, tx, flags | tapPREFER_QUEUE, j);
188  // If the transaction can't get into the queue for intrinsic
189  // reasons, and it can still be recovered, try to put it
190  // directly into the open ledger, else drop it.
191  if (queueResult.first == telCAN_NOT_QUEUE && shouldRecover)
192  return ripple::apply(app, view, *tx, flags, j);
193  return queueResult;
194  }();
195  if (result.second ||
196  result.first == terQUEUED)
197  return Result::success;
198  if (isTefFailure (result.first) ||
199  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<
234  STTx const>(sit);
235  ss << debugTxstr(tx) << ", ";
236  }
237  catch(std::exception const&)
238  {
239  ss << "THRO, ";
240  }
241  }
242  return ss.str();
243 }
244 
247 {
249  for(auto const& item : view->txs)
250  ss << debugTxstr(item.first) << ", ";
251  return ss.str();
252 }
253 
254 } // ripple
ripple::Application
Definition: Application.h:85
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:52
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:287
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:108
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:617
std::make_shared
T make_shared(T... args)
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
std::vector
STL class.
ripple::Overlay::foreach
std::enable_if_t<! std::is_void< typename UnaryFunc::return_type >::value, typename UnaryFunc::return_type > foreach(UnaryFunc f)
Visit every active peer and return a value The functor must:
Definition: Overlay.h:195
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:60
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:155
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:74
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:79
ripple::terQUEUED
@ terQUEUED
Definition: TER.h:203
std::map::emplace_hint
T emplace_hint(T... args)
ripple::CachedView
Wraps a DigestAwareReadView to provide caching.
Definition: CachedView.h:160
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:77
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:491
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:79
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:271
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:121
ripple::STTx
Definition: STTx.h:43
ripple::SerialIter
Definition: Serializer.h:311
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:60
ripple::HashRouter::shouldRelay
boost::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
Definition: HashRouter.cpp:107
ripple::tapPREFER_QUEUE
@ tapPREFER_QUEUE
Definition: ApplyView.h:46
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:45
ripple::STTx::getTransactionID
uint256 getTransactionID() const
Definition: STTx.h:120
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:41
ripple::Serializer
Definition: Serializer.h:43
ripple::STObject
Definition: STObject.h:51
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:73
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:102
ripple::OpenLedger::cache_
CachedSLEs & cache_
Definition: OpenLedger.h:53
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:481
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:126
std::stringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
ripple::OpenLedger::Result
Result
Definition: OpenLedger.h:185
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:177
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:208
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:59
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:486
ripple::ReadView::txs
txs_type txs
Definition: ReadView.h:401