rippled
Transaction.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/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/HashRouter.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/tx/apply.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/basics/safe_cast.h>
27 #include <ripple/core/DatabaseCon.h>
28 #include <ripple/protocol/ErrorCodes.h>
29 #include <ripple/protocol/Feature.h>
30 #include <ripple/protocol/jss.h>
31 #include <boost/optional.hpp>
32 
33 namespace ripple {
34 
36  std::shared_ptr<STTx const> const& stx,
37  std::string& reason,
38  Application& app) noexcept
39  : mTransaction(stx), mApp(app), j_(app.journal("Ledger"))
40 {
41  try
42  {
43  mTransactionID = mTransaction->getTransactionID();
44  }
45  catch (std::exception& e)
46  {
47  reason = e.what();
48  return;
49  }
50 
51  mStatus = NEW;
52 }
53 
54 //
55 // Misc.
56 //
57 
58 void
60 {
61  mStatus = ts;
62  mInLedger = lseq;
63 }
64 
66 Transaction::sqlTransactionStatus(boost::optional<std::string> const& status)
67 {
68  char const c = (status) ? (*status)[0] : safe_cast<char>(txnSqlUnknown);
69 
70  switch (c)
71  {
72  case txnSqlNew:
73  return NEW;
74  case txnSqlConflict:
75  return CONFLICTED;
76  case txnSqlHeld:
77  return HELD;
78  case txnSqlValidated:
79  return COMMITTED;
80  case txnSqlIncluded:
81  return INCLUDED;
82  }
83 
84  assert(c == txnSqlUnknown);
85  return INVALID;
86 }
87 
90  boost::optional<std::uint64_t> const& ledgerSeq,
91  boost::optional<std::string> const& status,
92  Blob const& rawTxn,
93  Application& app)
94 {
95  std::uint32_t const inLedger =
96  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
97 
98  SerialIter it(makeSlice(rawTxn));
99  auto txn = std::make_shared<STTx const>(it);
100  std::string reason;
101  auto tr = std::make_shared<Transaction>(txn, reason, app);
102 
103  tr->setStatus(sqlTransactionStatus(status));
104  tr->setLedger(inLedger);
105  return tr;
106 }
107 
110  TxSearched>
112 {
113  return load(id, app, boost::none, ec);
114 }
115 
118  TxSearched>
120  uint256 const& id,
121  Application& app,
123  error_code_i& ec)
124 {
125  using op = boost::optional<ClosedInterval<uint32_t>>;
126 
127  return load(id, app, op{range}, ec);
128 }
129 
132  TxSearched>
134  uint256 const& id,
135  Application& app,
136  boost::optional<ClosedInterval<uint32_t>> const& range,
137  error_code_i& ec)
138 {
139  std::string sql =
140  "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
141  "FROM Transactions WHERE TransID='";
142 
143  sql.append(to_string(id));
144  sql.append("';");
145 
146  boost::optional<std::uint64_t> ledgerSeq;
147  boost::optional<std::string> status;
148  Blob rawTxn, rawMeta;
149  {
150  auto db = app.getTxnDB().checkoutDb();
151  soci::blob sociRawTxnBlob(*db), sociRawMetaBlob(*db);
152  soci::indicator txn, meta;
153 
154  *db << sql, soci::into(ledgerSeq), soci::into(status),
155  soci::into(sociRawTxnBlob, txn), soci::into(sociRawMetaBlob, meta);
156 
157  auto const got_data = db->got_data();
158 
159  if ((!got_data || txn != soci::i_ok || meta != soci::i_ok) && !range)
160  return TxSearched::unknown;
161 
162  if (!got_data)
163  {
164  uint64_t count = 0;
165  soci::indicator rti;
166 
167  *db << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
168  "LedgerSeq BETWEEN "
169  << range->first() << " AND " << range->last() << ";",
170  soci::into(count, rti);
171 
172  if (!db->got_data() || rti != soci::i_ok)
173  return TxSearched::some;
174 
175  return count == (range->last() - range->first() + 1)
178  }
179 
180  convert(sociRawTxnBlob, rawTxn);
181  convert(sociRawMetaBlob, rawMeta);
182  }
183 
184  try
185  {
186  auto txn =
187  Transaction::transactionFromSQL(ledgerSeq, status, rawTxn, app);
188 
189  if (!ledgerSeq)
190  return std::pair{std::move(txn), nullptr};
191 
192  std::uint32_t inLedger =
193  rangeCheckedCast<std::uint32_t>(ledgerSeq.value());
194 
195  auto txMeta = std::make_shared<TxMeta>(id, inLedger, rawMeta);
196 
197  return std::pair{std::move(txn), std::move(txMeta)};
198  }
199  catch (std::exception& e)
200  {
201  JLOG(app.journal("Ledger").warn())
202  << "Unable to deserialize transaction from raw SQL value. Error: "
203  << e.what();
204 
206  }
207 
208  return TxSearched::unknown;
209 }
210 
211 // options 1 to include the date of the transaction
213 Transaction::getJson(JsonOptions options, bool binary) const
214 {
215  Json::Value ret(mTransaction->getJson(JsonOptions::none, binary));
216 
217  if (mInLedger)
218  {
219  ret[jss::inLedger] = mInLedger; // Deprecated.
220  ret[jss::ledger_index] = mInLedger;
221 
222  if (options == JsonOptions::include_date)
223  {
225  if (ct)
226  ret[jss::date] = ct->time_since_epoch().count();
227  }
228  }
229 
230  return ret;
231 }
232 
233 } // namespace ripple
ripple::COMMITTED
@ COMMITTED
Definition: Transaction.h:49
ripple::Transaction::sqlTransactionStatus
static TransStatus sqlTransactionStatus(boost::optional< std::string > const &status)
Definition: Transaction.cpp:66
ripple::Application
Definition: Application.h:97
ripple::Transaction::transactionFromSQL
static Transaction::pointer transactionFromSQL(boost::optional< std::uint64_t > const &ledgerSeq, boost::optional< std::string > const &status, Blob const &rawTxn, Application &app)
Definition: Transaction.cpp:89
ripple::JsonOptions::include_date
@ include_date
ripple::rpcDB_DESERIALIZATION
@ rpcDB_DESERIALIZATION
Definition: ErrorCodes.h:134
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:240
ripple::TxSearched::unknown
@ unknown
std::string
STL class.
std::shared_ptr
STL class.
ripple::Transaction::getJson
Json::Value getJson(JsonOptions options, bool binary=false) const
Definition: Transaction.cpp:213
std::exception
STL class.
ripple::JsonOptions
JsonOptions
Definition: STBase.h:34
std::pair
ripple::TxSearched::all
@ all
ripple::convert
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Definition: SociDB.cpp:156
ripple::TxSearched
TxSearched
Definition: Transaction.h:56
std::vector< unsigned char >
ripple::NEW
@ NEW
Definition: Transaction.h:45
ripple::HELD
@ HELD
Definition: Transaction.h:50
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::Transaction::mStatus
TransStatus mStatus
Definition: Transaction.h:339
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::TransStatus
TransStatus
Definition: Transaction.h:44
ripple::Transaction::mTransaction
std::shared_ptr< STTx const > mTransaction
Definition: Transaction.h:348
ripple::base_uint< 256 >
ripple::INCLUDED
@ INCLUDED
Definition: Transaction.h:47
ripple::txnSqlUnknown
@ txnSqlUnknown
Definition: STTx.h:39
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:176
ripple::Transaction::Transaction
Transaction(std::shared_ptr< STTx const > const &, std::string &, Application &) noexcept
Definition: Transaction.cpp:35
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::JsonOptions::none
@ none
ripple::txnSqlValidated
@ txnSqlValidated
Definition: STTx.h:37
ripple::SerialIter
Definition: Serializer.h:308
std::uint32_t
ripple::txnSqlHeld
@ txnSqlHeld
Definition: STTx.h:36
ripple::CONFLICTED
@ CONFLICTED
Definition: Transaction.h:48
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:53
ripple::Transaction::mInLedger
LedgerIndex mInLedger
Definition: Transaction.h:338
std::string::append
T append(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Transaction::load
static std::variant< std::pair< std::shared_ptr< Transaction >, std::shared_ptr< TxMeta > >, TxSearched > load(uint256 const &id, Application &app, error_code_i &ec)
Definition: Transaction.cpp:111
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::INVALID
@ INVALID
Definition: Transaction.h:46
ripple::LedgerMaster::getCloseTimeBySeq
boost::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1563
ripple::Transaction::setStatus
void setStatus(TransStatus status, std::uint32_t ledgerSeq)
Definition: Transaction.cpp:59
ripple::txnSqlIncluded
@ txnSqlIncluded
Definition: STTx.h:38
ripple::txnSqlConflict
@ txnSqlConflict
Definition: STTx.h:35
ripple::Transaction::mApp
Application & mApp
Definition: Transaction.h:349
ripple::txnSqlNew
@ txnSqlNew
Definition: STTx.h:34
ripple::ClosedInterval
boost::icl::closed_interval< T > ClosedInterval
A closed interval over the domain T.
Definition: RangeSet.h:44
std::exception::what
T what(T... args)
ripple::TxSearched::some
@ some
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::Application::getTxnDB
virtual DatabaseCon & getTxnDB()=0
std::variant