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 {
111  return boost::get<pointer>(load(id, app, boost::none, ec));
112 }
113 
114 boost::variant<Transaction::pointer, bool>
116  uint256 const& id,
117  Application& app,
119  error_code_i& ec)
120 {
121  using op = boost::optional<ClosedInterval<uint32_t>>;
122 
123  return load(id, app, op{range}, ec);
124 }
125 
126 boost::variant<Transaction::pointer, bool>
128  uint256 const& id,
129  Application& app,
130  boost::optional<ClosedInterval<uint32_t>> const& range,
131  error_code_i& ec)
132 {
133  std::string sql =
134  "SELECT LedgerSeq,Status,RawTxn "
135  "FROM Transactions WHERE TransID='";
136 
137  sql.append(to_string(id));
138  sql.append("';");
139 
140  boost::optional<std::uint64_t> ledgerSeq;
141  boost::optional<std::string> status;
142  Blob rawTxn;
143  {
144  auto db = app.getTxnDB().checkoutDb();
145  soci::blob sociRawTxnBlob(*db);
146  soci::indicator rti;
147 
148  *db << sql, soci::into(ledgerSeq), soci::into(status),
149  soci::into(sociRawTxnBlob, rti);
150 
151  auto const got_data = db->got_data();
152 
153  if ((!got_data || rti != soci::i_ok) && !range)
154  return nullptr;
155 
156  if (!got_data)
157  {
158  uint64_t count = 0;
159 
160  *db << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
161  "LedgerSeq BETWEEN "
162  << range->first() << " AND " << range->last() << ";",
163  soci::into(count, rti);
164 
165  if (!db->got_data() || rti != soci::i_ok)
166  return false;
167 
168  return count == (range->last() - range->first() + 1);
169  }
170 
171  convert(sociRawTxnBlob, rawTxn);
172  }
173 
174  try
175  {
176  return Transaction::transactionFromSQL(ledgerSeq, status, rawTxn, app);
177  }
178  catch (std::exception& e)
179  {
180  JLOG(app.journal("Ledger").warn())
181  << "Unable to deserialize transaction from raw SQL value. Error: "
182  << e.what();
183 
185  }
186 
187  return nullptr;
188 }
189 
190 // options 1 to include the date of the transaction
192 Transaction::getJson(JsonOptions options, bool binary) const
193 {
194  Json::Value ret(mTransaction->getJson(JsonOptions::none, binary));
195 
196  if (mInLedger)
197  {
198  ret[jss::inLedger] = mInLedger; // Deprecated.
199  ret[jss::ledger_index] = mInLedger;
200 
201  if (options == JsonOptions::include_date)
202  {
204  if (ct)
205  ret[jss::date] = ct->time_since_epoch().count();
206  }
207  }
208 
209  return ret;
210 }
211 
212 } // namespace ripple
ripple::COMMITTED
@ COMMITTED
Definition: Transaction.h:48
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
std::string
STL class.
std::shared_ptr
STL class.
ripple::Transaction::getJson
Json::Value getJson(JsonOptions options, bool binary=false) const
Definition: Transaction.cpp:192
std::exception
STL class.
ripple::JsonOptions
JsonOptions
Definition: STBase.h:34
ripple::convert
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Definition: SociDB.cpp:156
std::vector< unsigned char >
ripple::Transaction::load
static pointer load(uint256 const &id, Application &app, error_code_i &ec)
Definition: Transaction.cpp:109
ripple::NEW
@ NEW
Definition: Transaction.h:44
ripple::HELD
@ HELD
Definition: Transaction.h:49
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:324
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::TransStatus
TransStatus
Definition: Transaction.h:43
ripple::Transaction::mTransaction
std::shared_ptr< STTx const > mTransaction
Definition: Transaction.h:333
ripple::base_uint< 256 >
ripple::INCLUDED
@ INCLUDED
Definition: Transaction.h:46
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:47
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:323
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::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::INVALID
@ INVALID
Definition: Transaction.h:45
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:334
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)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::Application::getTxnDB
virtual DatabaseCon & getTxnDB()=0