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/misc/Transaction.h>
21 #include <ripple/app/tx/apply.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/core/DatabaseCon.h>
24 #include <ripple/app/ledger/LedgerMaster.h>
25 #include <ripple/app/main/Application.h>
26 #include <ripple/app/misc/HashRouter.h>
27 #include <ripple/basics/safe_cast.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::string& reason, Application& app)
37  noexcept
38  : mTransaction (stx)
39  , mApp (app)
40  , j_ (app.journal ("Ledger"))
41 {
42  try
43  {
44  mTransactionID = mTransaction->getTransactionID ();
45  }
46  catch (std::exception& e)
47  {
48  reason = e.what();
49  return;
50  }
51 
52  mStatus = NEW;
53 }
54 
55 //
56 // Misc.
57 //
58 
60 {
61  mStatus = ts;
62  mInLedger = lseq;
63 }
64 
66  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: return NEW;
73  case txnSqlConflict: return CONFLICTED;
74  case txnSqlHeld: return HELD;
75  case txnSqlValidated: return COMMITTED;
76  case txnSqlIncluded: return INCLUDED;
77  }
78 
79  assert (c == txnSqlUnknown);
80  return INVALID;
81 }
82 
84  boost::optional<std::uint64_t> const& ledgerSeq,
85  boost::optional<std::string> const& status,
86  Blob const& rawTxn,
87  Application& app)
88 {
89  std::uint32_t const inLedger =
90  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or (0));
91 
92  SerialIter it (makeSlice(rawTxn));
93  auto txn = std::make_shared<STTx const> (it);
94  std::string reason;
95  auto tr = std::make_shared<Transaction> (
96  txn, reason, app);
97 
98  tr->setStatus (sqlTransactionStatus (status));
99  tr->setLedger (inLedger);
100  return tr;
101 }
102 
104 {
105  return boost::get<pointer> (load (id, app, boost::none, ec));
106 }
107 
108 boost::variant<Transaction::pointer, bool>
110  error_code_i& ec)
111 {
112  using op = boost::optional<ClosedInterval<uint32_t>>;
113 
114  return load (id, app, op {range}, ec);
115 }
116 
117 boost::variant<Transaction::pointer, bool>
118 Transaction::load (uint256 const& id, Application& app, boost::optional<ClosedInterval<uint32_t>> const& range,
119  error_code_i& ec)
120 {
121  std::string sql = "SELECT LedgerSeq,Status,RawTxn "
122  "FROM Transactions WHERE TransID='";
123 
124  sql.append (to_string (id));
125  sql.append ("';");
126 
127  boost::optional<std::uint64_t> ledgerSeq;
128  boost::optional<std::string> status;
129  Blob rawTxn;
130  {
131  auto db = app.getTxnDB ().checkoutDb ();
132  soci::blob sociRawTxnBlob (*db);
133  soci::indicator rti;
134 
135  *db << sql, soci::into (ledgerSeq), soci::into (status),
136  soci::into (sociRawTxnBlob, rti);
137 
138  auto const got_data = db->got_data ();
139 
140  if ((!got_data || rti != soci::i_ok) && !range)
141  return nullptr;
142 
143  if (!got_data)
144  {
145  uint64_t count = 0;
146 
147  *db << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE LedgerSeq BETWEEN "
148  << range->first ()
149  << " AND "
150  << range->last ()
151  << ";",
152  soci::into (count, rti);
153 
154  if (!db->got_data () || rti != soci::i_ok)
155  return false;
156 
157  return count == (range->last () - range->first () + 1);
158  }
159 
160  convert (sociRawTxnBlob, rawTxn);
161  }
162 
163  try
164  {
166  ledgerSeq, status,
167  rawTxn, app);
168  }
169  catch (std::exception& e)
170  {
171  JLOG(app.journal("Ledger").warn())
172  << "Unable to deserialize transaction from raw SQL value. Error: "
173  << e.what();
174 
176  }
177 
178  return nullptr;
179 }
180 
181 // options 1 to include the date of the transaction
182 Json::Value Transaction::getJson (JsonOptions options, bool binary) const
183 {
184  Json::Value ret (mTransaction->getJson (JsonOptions::none, binary));
185 
186  if (mInLedger)
187  {
188  ret[jss::inLedger] = mInLedger; // Deprecated.
189  ret[jss::ledger_index] = mInLedger;
190 
191  if (options == JsonOptions::include_date)
192  {
193  auto ct = mApp.getLedgerMaster().
194  getCloseTimeBySeq (mInLedger);
195  if (ct)
196  ret[jss::date] = ct->time_since_epoch().count();
197  }
198  }
199 
200  return ret;
201 }
202 
203 } // ripple
ripple::COMMITTED
@ COMMITTED
Definition: Transaction.h:49
ripple::Transaction::sqlTransactionStatus
static TransStatus sqlTransactionStatus(boost::optional< std::string > const &status)
Definition: Transaction.cpp:65
ripple::Application
Definition: Application.h:85
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:83
ripple::JsonOptions::include_date
@ include_date
ripple::rpcDB_DESERIALIZATION
@ rpcDB_DESERIALIZATION
Definition: ErrorCodes.h:135
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:199
std::string
STL class.
std::shared_ptr
STL class.
ripple::Transaction::getJson
Json::Value getJson(JsonOptions options, bool binary=false) const
Definition: Transaction.cpp:182
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:150
std::vector< unsigned char >
ripple::Transaction::load
static pointer load(uint256 const &id, Application &app, error_code_i &ec)
Definition: Transaction.cpp:103
ripple::NEW
@ NEW
Definition: Transaction.h:45
ripple::HELD
@ HELD
Definition: Transaction.h:50
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::Transaction::mStatus
TransStatus mStatus
Definition: Transaction.h:295
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:304
ripple::base_uint< 256 >
ripple::INCLUDED
@ INCLUDED
Definition: Transaction.h:47
ripple::txnSqlUnknown
@ txnSqlUnknown
Definition: STTx.h:40
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:123
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:38
ripple::SerialIter
Definition: Serializer.h:311
std::uint32_t
ripple::txnSqlHeld
@ txnSqlHeld
Definition: STTx.h:37
ripple::CONFLICTED
@ CONFLICTED
Definition: Transaction.h:48
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:54
ripple::Transaction::mInLedger
LedgerIndex mInLedger
Definition: Transaction.h:294
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:46
ripple::Transaction::setStatus
void setStatus(TransStatus status, std::uint32_t ledgerSeq)
Definition: Transaction.cpp:59
ripple::txnSqlIncluded
@ txnSqlIncluded
Definition: STTx.h:39
ripple::txnSqlConflict
@ txnSqlConflict
Definition: STTx.h:36
ripple::Transaction::mApp
Application & mApp
Definition: Transaction.h:305
ripple::txnSqlNew
@ txnSqlNew
Definition: STTx.h:35
ripple::ClosedInterval
boost::icl::closed_interval< T > ClosedInterval
A closed interval over the domain T.
Definition: RangeSet.h:45
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::Application::getTxnDB
virtual DatabaseCon & getTxnDB()=0