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);
58  if (!sigVerify.first)
59  {
60  router.setFlags(id, SF_SIGBAD);
61  return {Validity::SigBad, sigVerify.second};
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  auto pfresult = preflight(app, view.rules(), tx, flags, j);
117  auto pcresult = preclaim(pfresult, app, view);
118  return doApply(pcresult, app, view);
119 }
120 
123  Application& app,
124  OpenView& view,
125  STTx const& txn,
126  bool retryAssured,
127  ApplyFlags flags,
128  beast::Journal j)
129 {
130  // Returns false if the transaction has need not be retried.
131  if (retryAssured)
132  flags = flags | tapRETRY;
133 
134  JLOG(j.debug()) << "TXN " << txn.getTransactionID()
135  << (retryAssured ? "/retry" : "/final");
136 
137  try
138  {
139  auto const result = apply(app, view, txn, flags, j);
140  if (result.second)
141  {
142  JLOG(j.debug())
143  << "Transaction applied: " << transHuman(result.first);
144  return ApplyResult::Success;
145  }
146 
147  if (isTefFailure(result.first) || isTemMalformed(result.first) ||
148  isTelLocal(result.first))
149  {
150  // failure
151  JLOG(j.debug())
152  << "Transaction failure: " << transHuman(result.first);
153  return ApplyResult::Fail;
154  }
155 
156  JLOG(j.debug()) << "Transaction retry: " << transHuman(result.first);
157  return ApplyResult::Retry;
158  }
159  catch (std::exception const&)
160  {
161  JLOG(j.warn()) << "Throws";
162  return ApplyResult::Fail;
163  }
164 }
165 
166 } // namespace ripple
ripple::Application
Definition: Application.h:97
std::string
STL class.
ripple::STTx::checkSign
std::pair< bool, std::string > checkSign(RequireFullyCanonicalSig requireCanonicalSig) const
Definition: STTx.cpp:175
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:88
std::pair
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
ripple::applyTransaction
ApplyResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:122
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:30
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:409
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:52
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
Definition: Feature.cpp:185
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:493
ripple::passesLocalChecks
bool passesLocalChecks(STObject const &st, std::string &reason)
Definition: STTx.cpp:495
ripple::Config
Definition: Config.h:67
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:564
ripple::ApplyResult::Retry
@ Retry
Should be retried in this ledger.
ripple::STTx
Definition: STTx.h:42
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Rules::enabled
bool enabled(uint256 const &id) const
Returns true if a feature is enabled.
Definition: ReadView.cpp:103
ripple::ApplyResult::Success
@ Success
Applied to this ledger.
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:202
ripple::STTx::getTransactionID
uint256 getTransactionID() const
Definition: STTx.h:131
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:39
ripple::preclaim
PreclaimResult preclaim(PreflightResult const &preflightResult, Application &app, OpenView const &view)
Gate a transaction based on static ledger information.
Definition: applySteps.cpp:429
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::Validity::Valid
@ Valid
Signature and local checks are good / passed.
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:552
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:127
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:129
ripple::HashRouter::setFlags
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:96
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:558