rippled
Loading...
Searching...
No Matches
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 <xrpld/app/tx/detail/ApplyContext.h>
21#include <xrpld/app/tx/detail/InvariantCheck.h>
22
23#include <xrpl/basics/Log.h>
24#include <xrpl/beast/utility/instrumentation.h>
25#include <xrpl/json/to_string.h>
26
27namespace ripple {
28
30 Application& app_,
31 OpenView& base,
32 std::optional<uint256 const> const& parentBatchId,
33 STTx const& tx_,
34 TER preclaimResult_,
35 XRPAmount baseFee_,
36 ApplyFlags flags,
37 beast::Journal journal_)
38 : app(app_)
39 , tx(tx_)
40 , preclaimResult(preclaimResult_)
41 , baseFee(baseFee_)
42 , journal(journal_)
43 , base_(base)
44 , flags_(flags)
45 , parentBatchId_(parentBatchId)
46{
47 XRPL_ASSERT(
48 parentBatchId.has_value() == ((flags_ & tapBATCH) == tapBATCH),
49 "Parent Batch ID should be set if batch apply flag is set");
50 view_.emplace(&base_, flags_);
51}
52
53void
55{
56 view_.emplace(&base_, flags_);
57}
58
61{
62 return view_->apply(
64}
65
68{
69 return view_->size();
70}
71
72void
74 uint256 const&,
75 bool,
77 std::shared_ptr<SLE const> const&)> const& func)
78{
79 view_->visit(base_, func);
80}
81
82TER
84{
85 // If we already failed invariant checks before and we are now attempting to
86 // only charge a fee, and even that fails the invariant checks something is
87 // very wrong. We switch to tefINVARIANT_FAILED, which does NOT get included
88 // in a ledger.
89
90 return (result == tecINVARIANT_FAILED || result == tefINVARIANT_FAILED)
93}
94
95template <std::size_t... Is>
96TER
98 TER const result,
99 XRPAmount const fee,
101{
102 try
103 {
104 auto checkers = getInvariantChecks();
105
106 // call each check's per-entry method
107 visit([&checkers](
108 uint256 const& index,
109 bool isDelete,
110 std::shared_ptr<SLE const> const& before,
112 (..., std::get<Is>(checkers).visitEntry(isDelete, before, after));
113 });
114
115 // Note: do not replace this logic with a `...&&` fold expression.
116 // The fold expression will only run until the first check fails (it
117 // short-circuits). While the logic is still correct, the log
118 // message won't be. Every failed invariant should write to the log,
119 // not just the first one.
120 std::array<bool, sizeof...(Is)> finalizers{
121 {std::get<Is>(checkers).finalize(
122 tx, result, fee, *view_, journal)...}};
123
124 // call each check's finalizer to see that it passes
125 if (!std::all_of(
126 finalizers.cbegin(), finalizers.cend(), [](auto const& b) {
127 return b;
128 }))
129 {
130 JLOG(journal.fatal())
131 << "Transaction has failed one or more invariants: "
133
134 return failInvariantCheck(result);
135 }
136 }
137 catch (std::exception const& ex)
138 {
139 JLOG(journal.fatal())
140 << "Transaction caused an exception in an invariant"
141 << ", ex: " << ex.what()
142 << ", tx: " << to_string(tx.getJson(JsonOptions::none));
143
144 return failInvariantCheck(result);
145 }
146
147 return result;
148}
149
150TER
152{
153 XRPL_ASSERT(
154 isTesSuccess(result) || isTecClaim(result),
155 "ripple::ApplyContext::checkInvariants : is tesSUCCESS or tecCLAIM");
156
158 result,
159 fee,
160 std::make_index_sequence<std::tuple_size<InvariantChecks>::value>{});
161}
162
163} // namespace ripple
T all_of(T... args)
A generic endpoint for log messages.
Definition: Journal.h:60
Stream fatal() const
Definition: Journal.h:352
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.
std::optional< TxMeta > apply(TER)
Apply the transaction result to the base.
ApplyContext(Application &app, OpenView &base, std::optional< uint256 const > const &parentBatchId, STTx const &tx, TER preclaimResult, XRPAmount baseFee, ApplyFlags flags, beast::Journal journal=beast::Journal{beast::Journal::getNullSink()})
void discard()
Discard changes and start fresh.
TER failInvariantCheck(TER const result)
beast::Journal const journal
Definition: ApplyContext.h:75
std::size_t size()
Get the number of unapplied changes.
std::optional< ApplyViewImpl > view_
Definition: ApplyContext.h:156
TER checkInvariants(TER const result, XRPAmount const fee)
Applies all invariant checkers one by one.
std::optional< uint256 const > parentBatchId_
Definition: ApplyContext.h:159
TER checkInvariantsHelper(TER const result, XRPAmount const fee, std::index_sequence< Is... >)
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:66
Json::Value getJson(JsonOptions options) const override
Definition: STTx.cpp:305
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
@ tefINVARIANT_FAILED
Definition: TER.h:183
@ tecINVARIANT_FAILED
Definition: TER.h:313
bool isTesSuccess(TER x) noexcept
Definition: TER.h:672
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition: View.cpp:2727
InvariantChecks getInvariantChecks()
get a tuple of all invariant checks
ApplyFlags
Definition: ApplyView.h:31
@ tapDRY_RUN
Definition: ApplyView.h:50
@ tapBATCH
Definition: ApplyView.h:46
bool isTecClaim(TER x) noexcept
Definition: TER.h:678
T has_value(T... args)
T what(T... args)