rippled
Loading...
Searching...
No Matches
Transaction.cpp
1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/main/Application.h>
3#include <xrpld/app/misc/HashRouter.h>
4#include <xrpld/app/misc/Transaction.h>
5#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
6#include <xrpld/app/tx/apply.h>
7#include <xrpld/rpc/CTID.h>
8
9#include <xrpl/basics/safe_cast.h>
10#include <xrpl/protocol/ErrorCodes.h>
11#include <xrpl/protocol/jss.h>
12
13namespace ripple {
14
17 std::string& reason,
18 Application& app) noexcept
19 : mTransaction(stx), mApp(app), j_(app.journal("Ledger"))
20{
21 try
22 {
23 mTransactionID = mTransaction->getTransactionID();
24 }
25 catch (std::exception& e)
26 {
27 reason = e.what();
28 return;
29 }
30
31 mStatus = NEW;
32}
33
34//
35// Misc.
36//
37
38void
40 TransStatus ts,
41 std::uint32_t lseq,
44{
45 mStatus = ts;
46 mLedgerIndex = lseq;
47 if (tseq)
48 mTxnSeq = tseq;
49 if (netID)
50 mNetworkID = netID;
51}
52
54Transaction::sqlTransactionStatus(boost::optional<std::string> const& status)
55{
56 char const c = (status) ? (*status)[0] : safe_cast<char>(txnSqlUnknown);
57
58 switch (c)
59 {
60 case txnSqlNew:
61 return NEW;
62 case txnSqlConflict:
63 return CONFLICTED;
64 case txnSqlHeld:
65 return HELD;
66 case txnSqlValidated:
67 return COMMITTED;
68 case txnSqlIncluded:
69 return INCLUDED;
70 }
71
72 XRPL_ASSERT(
73 c == txnSqlUnknown,
74 "ripple::Transaction::sqlTransactionStatus : unknown transaction "
75 "status");
76 return INVALID;
77}
78
81 boost::optional<std::uint64_t> const& ledgerSeq,
82 boost::optional<std::string> const& status,
83 Blob const& rawTxn,
84 Application& app)
85{
86 std::uint32_t const inLedger =
87 rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
88
89 SerialIter it(makeSlice(rawTxn));
90 auto txn = std::make_shared<STTx const>(it);
91 std::string reason;
92 auto tr = std::make_shared<Transaction>(txn, reason, app);
93
94 tr->setStatus(sqlTransactionStatus(status));
95 tr->setLedger(inLedger);
96 return tr;
97}
98
103{
104 return load(id, app, std::nullopt, ec);
105}
106
111 uint256 const& id,
112 Application& app,
114 error_code_i& ec)
115{
117
118 return load(id, app, op{range}, ec);
119}
120
125 uint256 const& id,
126 Application& app,
128 error_code_i& ec)
129{
130 auto const db = dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
131
132 if (!db)
133 {
134 Throw<std::runtime_error>("Failed to get relational database");
135 }
136
137 return db->getTransaction(id, range, ec);
138}
139
140// options 1 to include the date of the transaction
142Transaction::getJson(JsonOptions options, bool binary) const
143{
144 // Note, we explicitly suppress `include_date` option here
145 Json::Value ret(
146 mTransaction->getJson(options & ~JsonOptions::include_date, binary));
147
148 // NOTE Binary STTx::getJson output might not be a JSON object
149 if (ret.isObject() && mLedgerIndex)
150 {
151 if (!(options & JsonOptions::disable_API_prior_V2))
152 {
153 // Behaviour before API version 2
154 ret[jss::inLedger] = mLedgerIndex;
155 }
156
157 // TODO: disable_API_prior_V3 to disable output of both `date` and
158 // `ledger_index` elements (taking precedence over include_date)
159 ret[jss::ledger_index] = mLedgerIndex;
160
161 if (options & JsonOptions::include_date)
162 {
164 if (ct)
165 ret[jss::date] = ct->time_since_epoch().count();
166 }
167
168 // compute outgoing CTID
169 // override local network id if it's explicitly in the txn
171 if (mTransaction->isFieldPresent(sfNetworkID))
172 netID = mTransaction->getFieldU32(sfNetworkID);
173
174 if (mTxnSeq && netID)
175 {
176 std::optional<std::string> const ctid =
178 if (ctid)
179 ret[jss::ctid] = *ctid;
180 }
181 }
182
183 return ret;
184}
185
186} // namespace ripple
Represents a JSON value.
Definition json_value.h:130
bool isObject() const
virtual LedgerMaster & getLedgerMaster()=0
virtual RelationalDatabase & getRelationalDatabase()=0
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
static Transaction::pointer transactionFromSQL(boost::optional< std::uint64_t > const &ledgerSeq, boost::optional< std::string > const &status, Blob const &rawTxn, Application &app)
Transaction(std::shared_ptr< STTx const > const &, std::string &, Application &) noexcept
std::optional< uint32_t > mNetworkID
std::optional< uint32_t > mTxnSeq
LedgerIndex mLedgerIndex
static std::variant< std::pair< std::shared_ptr< Transaction >, std::shared_ptr< TxMeta > >, TxSearched > load(uint256 const &id, Application &app, error_code_i &ec)
Application & mApp
void setStatus(TransStatus status, std::uint32_t ledgerSeq, std::optional< uint32_t > transactionSeq=std::nullopt, std::optional< uint32_t > networkID=std::nullopt)
static TransStatus sqlTransactionStatus(boost::optional< std::string > const &status)
Json::Value getJson(JsonOptions options, bool binary=false) const
TransStatus mStatus
std::shared_ptr< STTx const > mTransaction
T is_same_v
std::optional< std::string > encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
Encodes ledger sequence, transaction index, and network ID into a CTID string.
Definition CTID.h:34
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ CONFLICTED
Definition Transaction.h:31
@ COMMITTED
Definition Transaction.h:32
boost::icl::closed_interval< T > ClosedInterval
A closed interval over the domain T.
Definition RangeSet.h:26
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:225
@ txnSqlIncluded
Definition STTx.h:24
@ txnSqlUnknown
Definition STTx.h:25
@ txnSqlConflict
Definition STTx.h:21
@ txnSqlHeld
Definition STTx.h:22
@ txnSqlNew
Definition STTx.h:20
@ txnSqlValidated
Definition STTx.h:23
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:35
Note, should be treated as flags that can be | and &.
Definition STBase.h:18
T what(T... args)