rippled
ApplyContext.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/tx/impl/ApplyContext.h>
21 #include <ripple/app/tx/impl/InvariantCheck.h>
22 #include <ripple/app/tx/impl/Transactor.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/json/to_string.h>
25 #include <ripple/protocol/Feature.h>
26 #include <ripple/protocol/Indexes.h>
27 #include <cassert>
28 
29 namespace ripple {
30 
32  Application& app_,
33  OpenView& base,
34  STTx const& tx_,
35  TER preclaimResult_,
36  XRPAmount baseFee_,
37  ApplyFlags flags,
38  beast::Journal journal_)
39  : app(app_)
40  , tx(tx_)
41  , preclaimResult(preclaimResult_)
42  , baseFee(baseFee_)
43  , journal(journal_)
44  , base_(base)
45  , flags_(flags)
46 {
47  view_.emplace(&base_, flags_);
48 }
49 
50 void
52 {
53  view_.emplace(&base_, flags_);
54 }
55 
56 void
58 {
59  view_->apply(base_, tx, ter, journal);
60 }
61 
64 {
65  return view_->size();
66 }
67 
68 void
70  uint256 const&,
71  bool,
73  std::shared_ptr<SLE const> const&)> const& func)
74 {
75  view_->visit(base_, func);
76 }
77 
78 TER
80 {
81  // If we already failed invariant checks before and we are now attempting to
82  // only charge a fee, and even that fails the invariant checks something is
83  // very wrong. We switch to tefINVARIANT_FAILED, which does NOT get included
84  // in a ledger.
85 
86  return (result == tecINVARIANT_FAILED || result == tefINVARIANT_FAILED)
89 }
90 
91 template <std::size_t... Is>
92 TER
94  TER const result,
95  XRPAmount const fee,
97 {
98  try
99  {
100  auto checkers = getInvariantChecks();
101 
102  // call each check's per-entry method
103  visit([&checkers](
104  uint256 const& index,
105  bool isDelete,
106  std::shared_ptr<SLE const> const& before,
108  (..., std::get<Is>(checkers).visitEntry(isDelete, before, after));
109  });
110 
111  // Note: do not replace this logic with a `...&&` fold expression.
112  // The fold expression will only run until the first check fails (it
113  // short-circuits). While the logic is still correct, the log
114  // message won't be. Every failed invariant should write to the log,
115  // not just the first one.
116  std::array<bool, sizeof...(Is)> finalizers{
117  {std::get<Is>(checkers).finalize(
118  tx, result, fee, *view_, journal)...}};
119 
120  // call each check's finalizer to see that it passes
121  if (!std::all_of(
122  finalizers.cbegin(), finalizers.cend(), [](auto const& b) {
123  return b;
124  }))
125  {
126  JLOG(journal.fatal())
127  << "Transaction has failed one or more invariants: "
129 
130  return failInvariantCheck(result);
131  }
132  }
133  catch (std::exception const& ex)
134  {
135  JLOG(journal.fatal())
136  << "Transaction caused an exception in an invariant"
137  << ", ex: " << ex.what()
138  << ", tx: " << to_string(tx.getJson(JsonOptions::none));
139 
140  return failInvariantCheck(result);
141  }
142 
143  return result;
144 }
145 
146 TER
148 {
149  assert(isTesSuccess(result) || isTecClaim(result));
150 
151  return checkInvariantsHelper(
152  result,
153  fee,
154  std::make_index_sequence<std::tuple_size<InvariantChecks>::value>{});
155 }
156 
157 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Application
Definition: Application.h:115
ripple::tecINVARIANT_FAILED
@ tecINVARIANT_FAILED
Definition: TER.h:280
std::shared_ptr
STL class.
ripple::ApplyContext::checkInvariants
TER checkInvariants(TER const result, XRPAmount const fee)
Applies all invariant checkers one by one.
Definition: ApplyContext.cpp:147
std::exception
STL class.
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:597
ripple::tefINVARIANT_FAILED
@ tefINVARIANT_FAILED
Definition: TER.h:165
std::index_sequence
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::ApplyContext::flags_
ApplyFlags flags_
Definition: ApplyContext.h:125
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:29
ripple::ApplyContext::journal
const beast::Journal journal
Definition: ApplyContext.h:51
std::function
std::all_of
T all_of(T... args)
ripple::ApplyContext::base_
OpenView & base_
Definition: ApplyContext.h:124
ripple::isTecClaim
bool isTecClaim(TER x)
Definition: TER.h:603
ripple::base_uint< 256 >
ripple::JsonOptions::none
@ none
ripple::TERSubset< CanCvtToTER >
std::array
STL class.
ripple::ApplyContext::discard
void discard()
Discard changes and start fresh.
Definition: ApplyContext.cpp:51
ripple::STTx
Definition: STTx.h:45
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::STTx::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STTx.cpp:229
ripple::ApplyContext::apply
void apply(TER)
Apply the transaction result to the base.
Definition: ApplyContext.cpp:57
ripple::ApplyContext::visit
void visit(std::function< void(uint256 const &key, bool isDelete, std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)> const &func)
Visit unapplied changes.
Definition: ApplyContext.cpp:69
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
cassert
ripple::ApplyContext::checkInvariantsHelper
TER checkInvariantsHelper(TER const result, XRPAmount const fee, std::index_sequence< Is... >)
Definition: ApplyContext.cpp:93
ripple::ApplyContext::ApplyContext
ApplyContext(Application &app, OpenView &base, STTx const &tx, TER preclaimResult, XRPAmount baseFee, ApplyFlags flags, beast::Journal=beast::Journal{beast::Journal::getNullSink()})
Definition: ApplyContext.cpp:31
ripple::ApplyContext::view_
std::optional< ApplyViewImpl > view_
Definition: ApplyContext.h:126
ripple::after
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition: Escrow.cpp:88
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::getInvariantChecks
InvariantChecks getInvariantChecks()
get a tuple of all invariant checks
Definition: InvariantCheck.h:392
ripple::ApplyContext::size
std::size_t size()
Get the number of unapplied changes.
Definition: ApplyContext.cpp:63
ripple::ApplyContext::tx
STTx const & tx
Definition: ApplyContext.h:48
std::exception::what
T what(T... args)
ripple::ApplyContext::failInvariantCheck
TER failInvariantCheck(TER const result)
Definition: ApplyContext.cpp:79
ripple::XRPAmount
Definition: XRPAmount.h:46