rippled
apply.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/misc/HashRouter.h>
21 #include <ripple/app/tx/apply.h>
22 #include <ripple/app/tx/applySteps.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/protocol/Feature.h>
25 
26 namespace ripple {
27 
28 // These are the same flags defined as SF_PRIVATE1-4 in HashRouter.h
29 #define SF_SIGBAD SF_PRIVATE1 // Signature is bad
30 #define SF_SIGGOOD SF_PRIVATE2 // Signature is good
31 #define SF_LOCALBAD SF_PRIVATE3 // Local checks failed
32 #define SF_LOCALGOOD SF_PRIVATE4 // Local checks passed
33 
34 //------------------------------------------------------------------------------
35 
38  HashRouter& router,
39  STTx const& tx,
40  Rules const& rules,
41  Config const& config)
42 {
43  auto const id = tx.getTransactionID();
44  auto const flags = router.getFlags(id);
45  if (flags & SF_SIGBAD)
46  // Signature is known bad
47  return {Validity::SigBad, "Transaction has bad signature."};
48 
49  if (!(flags & SF_SIGGOOD))
50  {
51  // Don't know signature state. Check it.
52  auto const requireCanonicalSig =
56 
57  auto const sigVerify = tx.checkSign(requireCanonicalSig, rules);
58  if (!sigVerify)
59  {
60  router.setFlags(id, SF_SIGBAD);
61  return {Validity::SigBad, sigVerify.error()};
62  }
63  router.setFlags(id, SF_SIGGOOD);
64  }
65 
66  // Signature is now known good
67  if (flags & SF_LOCALBAD)
68  // ...but the local checks
69  // are known bad.
70  return {Validity::SigGoodOnly, "Local checks failed."};
71 
72  if (flags & SF_LOCALGOOD)
73  // ...and the local checks
74  // are known good.
75  return {Validity::Valid, ""};
76 
77  // Do the local checks
78  std::string reason;
79  if (!passesLocalChecks(tx, reason))
80  {
81  router.setFlags(id, SF_LOCALBAD);
82  return {Validity::SigGoodOnly, reason};
83  }
84  router.setFlags(id, SF_LOCALGOOD);
85  return {Validity::Valid, ""};
86 }
87 
88 void
89 forceValidity(HashRouter& router, uint256 const& txid, Validity validity)
90 {
91  int flags = 0;
92  switch (validity)
93  {
94  case Validity::Valid:
95  flags |= SF_LOCALGOOD;
96  [[fallthrough]];
98  flags |= SF_SIGGOOD;
99  [[fallthrough]];
100  case Validity::SigBad:
101  // would be silly to call directly
102  break;
103  }
104  if (flags)
105  router.setFlags(txid, flags);
106 }
107 
110  Application& app,
111  OpenView& view,
112  STTx const& tx,
113  ApplyFlags flags,
114  beast::Journal j)
115 {
116  STAmountSO stAmountSO{view.rules().enabled(fixSTAmountCanonicalize)};
117  NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)};
118 
119  auto pfresult = preflight(app, view.rules(), tx, flags, j);
120  auto pcresult = preclaim(pfresult, app, view);
121  return doApply(pcresult, app, view);
122 }
123 
126  Application& app,
127  OpenView& view,
128  STTx const& txn,
129  bool retryAssured,
130  ApplyFlags flags,
131  beast::Journal j)
132 {
133  // Returns false if the transaction has need not be retried.
134  if (retryAssured)
135  flags = flags | tapRETRY;
136 
137  JLOG(j.debug()) << "TXN " << txn.getTransactionID()
138  << (retryAssured ? "/retry" : "/final");
139 
140  try
141  {
142  auto const result = apply(app, view, txn, flags, j);
143  if (result.second)
144  {
145  JLOG(j.debug())
146  << "Transaction applied: " << transHuman(result.first);
147  return ApplyResult::Success;
148  }
149 
150  if (isTefFailure(result.first) || isTemMalformed(result.first) ||
151  isTelLocal(result.first))
152  {
153  // failure
154  JLOG(j.debug())
155  << "Transaction failure: " << transHuman(result.first);
156  return ApplyResult::Fail;
157  }
158 
159  JLOG(j.debug()) << "Transaction retry: " << transHuman(result.first);
160  return ApplyResult::Retry;
161  }
162  catch (std::exception const& ex)
163  {
164  JLOG(j.warn()) << "Throws: " << ex.what();
165  return ApplyResult::Fail;
166  }
167 }
168 
169 } // namespace ripple
ripple::Application
Definition: Application.h:115
ripple::STAmountSO
RAII class to set and restore the STAmount canonicalize switchover.
Definition: STAmount.h:549
std::string
STL class.
ripple::Rules::enabled
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:94
std::exception
STL class.
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::HashRouter::getFlags
int getFlags(uint256 const &key)
Definition: HashRouter.cpp:94
std::pair
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::applyTransaction
ApplyResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:125
ripple::NumberSO
RAII class to set and restore the Number switchover.
Definition: IOUAmount.h:201
ripple::fixSTAmountCanonicalize
const uint256 fixSTAmountCanonicalize
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:29
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::Validity
Validity
Describes the pre-processing validity of a transaction.
Definition: apply.h:40
ripple::preflight
PreflightResult preflight(Application &app, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
Definition: applySteps.cpp:473
ripple::ApplyResult
ApplyResult
Enum class for return value from applyTransaction
Definition: apply.h:134
ripple::HashRouter
Routing table for objects identified by hash.
Definition: HashRouter.h:53
ripple::forceValidity
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition: apply.cpp:89
ripple::Validity::SigGoodOnly
@ SigGoodOnly
Signature is good, but local checks fail.
ripple::STTx::RequireFullyCanonicalSig::no
@ no
ripple::base_uint< 256 >
ripple::featureRequireFullyCanonicalSig
const uint256 featureRequireFullyCanonicalSig
ripple::checkValidity
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
Definition: apply.cpp:37
ripple::doApply
std::pair< TER, bool > doApply(PreclaimResult const &preclaimResult, Application &app, OpenView &view)
Apply a prechecked transaction to an OpenView.
Definition: applySteps.cpp:551
ripple::passesLocalChecks
bool passesLocalChecks(STObject const &st, std::string &reason)
Definition: STTx.cpp:530
ripple::Config
Definition: Config.h:89
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:585
ripple::ApplyResult::Retry
@ Retry
Should be retried in this ledger.
ripple::STTx
Definition: STTx.h:45
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::ApplyResult::Success
@ Success
Applied to this ledger.
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:219
ripple::STTx::getTransactionID
uint256 getTransactionID() const
Definition: STTx.h:191
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:38
ripple::preclaim
PreclaimResult preclaim(PreflightResult const &preflightResult, Application &app, OpenView const &view)
Gate a transaction based on static ledger information.
Definition: applySteps.cpp:493
ripple::ApplyResult::Fail
@ Fail
Should not be retried in this ledger.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::STTx::RequireFullyCanonicalSig::yes
@ yes
ripple::STTx::checkSign
Expected< void, std::string > checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Definition: STTx.cpp:209
ripple::Validity::Valid
@ Valid
Signature and local checks are good / passed.
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:573
ripple::fixUniversalNumber
const uint256 fixUniversalNumber
ripple::Rules
Rules controlling protocol behavior.
Definition: Rules.h:33
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::Validity::SigBad
@ SigBad
Signature is bad. Didn't do local checks.
ripple::OpenView::rules
Rules const & rules() const override
Returns the tx processing rules.
Definition: OpenView.cpp:152
ripple::HashRouter::setFlags
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:102
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:579
std::exception::what
T what(T... args)