rippled
LedgerToJson.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2015 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/LedgerToJson.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/TxQ.h>
23 #include <ripple/basics/base_uint.h>
24 #include <ripple/core/Pg.h>
25 #include <ripple/rpc/Context.h>
26 #include <ripple/rpc/DeliveredAmount.h>
27 
28 namespace ripple {
29 
30 namespace {
31 
32 bool
33 isFull(LedgerFill const& fill)
34 {
35  return fill.options & LedgerFill::full;
36 }
37 
38 bool
39 isExpanded(LedgerFill const& fill)
40 {
41  return isFull(fill) || (fill.options & LedgerFill::expand);
42 }
43 
44 bool
45 isBinary(LedgerFill const& fill)
46 {
47  return fill.options & LedgerFill::binary;
48 }
49 
50 template <class Object>
51 void
52 fillJson(Object& json, bool closed, LedgerInfo const& info, bool bFull)
53 {
54  json[jss::parent_hash] = to_string(info.parentHash);
55  json[jss::ledger_index] = to_string(info.seq);
56  json[jss::seqNum] = to_string(info.seq); // DEPRECATED
57 
58  if (closed)
59  {
60  json[jss::closed] = true;
61  }
62  else if (!bFull)
63  {
64  json[jss::closed] = false;
65  return;
66  }
67 
68  json[jss::ledger_hash] = to_string(info.hash);
69  json[jss::transaction_hash] = to_string(info.txHash);
70  json[jss::account_hash] = to_string(info.accountHash);
71  json[jss::total_coins] = to_string(info.drops);
72 
73  // These next three are DEPRECATED.
74  json[jss::hash] = to_string(info.hash);
75  json[jss::totalCoins] = to_string(info.drops);
76  json[jss::accepted] = closed;
77  json[jss::close_flags] = info.closeFlags;
78 
79  // Always show fields that contribute to the ledger hash
80  json[jss::parent_close_time] =
81  info.parentCloseTime.time_since_epoch().count();
82  json[jss::close_time] = info.closeTime.time_since_epoch().count();
83  json[jss::close_time_resolution] = info.closeTimeResolution.count();
84 
85  if (info.closeTime != NetClock::time_point{})
86  {
87  json[jss::close_time_human] = to_string(info.closeTime);
88  if (!getCloseAgree(info))
89  json[jss::close_time_estimated] = true;
90  }
91 }
92 
93 template <class Object>
94 void
95 fillJsonBinary(Object& json, bool closed, LedgerInfo const& info)
96 {
97  if (!closed)
98  json[jss::closed] = false;
99  else
100  {
101  json[jss::closed] = true;
102 
103  Serializer s;
104  addRaw(info, s);
105  json[jss::ledger_data] = strHex(s.peekData());
106  }
107 }
108 
110 fillJsonTx(
111  LedgerFill const& fill,
112  bool bBinary,
113  bool bExpanded,
114  std::shared_ptr<STTx const> const& txn,
115  std::shared_ptr<STObject const> const& stMeta)
116 {
117  if (!bExpanded)
118  return to_string(txn->getTransactionID());
119 
121  auto const txnType = txn->getTxnType();
122  if (bBinary)
123  {
124  txJson[jss::tx_blob] = serializeHex(*txn);
125  if (stMeta)
126  txJson[jss::meta] = serializeHex(*stMeta);
127  }
128  else
129  {
130  copyFrom(txJson, txn->getJson(JsonOptions::none));
131  if (stMeta)
132  {
133  txJson[jss::metaData] = stMeta->getJson(JsonOptions::none);
134 
135  // If applicable, insert delivered amount
136  if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
138  txJson[jss::metaData],
139  fill.ledger,
140  txn,
141  {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
142  }
143  }
144 
145  if ((fill.options & LedgerFill::ownerFunds) &&
146  txn->getTxnType() == ttOFFER_CREATE)
147  {
148  auto const account = txn->getAccountID(sfAccount);
149  auto const amount = txn->getFieldAmount(sfTakerGets);
150 
151  // If the offer create is not self funded then add the
152  // owner balance
153  if (account != amount.getIssuer())
154  {
155  auto const ownerFunds = accountFunds(
156  fill.ledger,
157  account,
158  amount,
160  beast::Journal{beast::Journal::getNullSink()});
161  txJson[jss::owner_funds] = ownerFunds.getText();
162  }
163  }
164 
165  return txJson;
166 }
167 
168 template <class Object>
169 void
170 fillJsonTx(Object& json, LedgerFill const& fill)
171 {
172  auto&& txns = setArray(json, jss::transactions);
173  auto bBinary = isBinary(fill);
174  auto bExpanded = isExpanded(fill);
175 
176  try
177  {
178  auto appendAll = [&](auto const& txs) {
179  for (auto& i : txs)
180  {
181  txns.append(
182  fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
183  }
184  };
185 
186  if (fill.context && fill.context->app.config().reporting())
187  {
188  appendAll(flatFetchTransactions(fill.ledger, fill.context->app));
189  }
190  else
191  {
192  appendAll(fill.ledger.txs);
193  }
194  }
195  catch (std::exception const& ex)
196  {
197  // Nothing the user can do about this.
198  if (fill.context)
199  {
200  JLOG(fill.context->j.error())
201  << "Exception in " << __func__ << ": " << ex.what();
202  }
203  }
204 }
205 
206 template <class Object>
207 void
208 fillJsonState(Object& json, LedgerFill const& fill)
209 {
210  auto& ledger = fill.ledger;
211  auto&& array = Json::setArray(json, jss::accountState);
212  auto expanded = isExpanded(fill);
213  auto binary = isBinary(fill);
214 
215  for (auto const& sle : ledger.sles)
216  {
217  if (fill.type == ltANY || sle->getType() == fill.type)
218  {
219  if (binary)
220  {
221  auto&& obj = appendObject(array);
222  obj[jss::hash] = to_string(sle->key());
223  obj[jss::tx_blob] = serializeHex(*sle);
224  }
225  else if (expanded)
226  array.append(sle->getJson(JsonOptions::none));
227  else
228  array.append(to_string(sle->key()));
229  }
230  }
231 }
232 
233 template <class Object>
234 void
235 fillJsonQueue(Object& json, LedgerFill const& fill)
236 {
237  auto&& queueData = Json::setArray(json, jss::queue_data);
238  auto bBinary = isBinary(fill);
239  auto bExpanded = isExpanded(fill);
240 
241  for (auto const& tx : fill.txQueue)
242  {
243  auto&& txJson = appendObject(queueData);
244  txJson[jss::fee_level] = to_string(tx.feeLevel);
245  if (tx.lastValid)
246  txJson[jss::LastLedgerSequence] = *tx.lastValid;
247 
248  txJson[jss::fee] = to_string(tx.consequences.fee());
249  auto const spend =
250  tx.consequences.potentialSpend() + tx.consequences.fee();
251  txJson[jss::max_spend_drops] = to_string(spend);
252  txJson[jss::auth_change] = tx.consequences.isBlocker();
253 
254  txJson[jss::account] = to_string(tx.account);
255  txJson["retries_remaining"] = tx.retriesRemaining;
256  txJson["preflight_result"] = transToken(tx.preflightResult);
257  if (tx.lastResult)
258  txJson["last_result"] = transToken(*tx.lastResult);
259 
260  txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded, tx.txn, nullptr);
261  }
262 }
263 
264 template <class Object>
265 void
266 fillJson(Object& json, LedgerFill const& fill)
267 {
268  // TODO: what happens if bBinary and bExtracted are both set?
269  // Is there a way to report this back?
270  auto bFull = isFull(fill);
271  if (isBinary(fill))
272  fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info());
273  else
274  fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
275 
276  if (bFull || fill.options & LedgerFill::dumpTxrp)
277  fillJsonTx(json, fill);
278 
279  if (bFull || fill.options & LedgerFill::dumpState)
280  fillJsonState(json, fill);
281 }
282 
283 } // namespace
284 
285 void
286 addJson(Json::Value& json, LedgerFill const& fill)
287 {
288  auto&& object = Json::addObject(json, jss::ledger);
289  fillJson(object, fill);
290 
291  if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty())
292  fillJsonQueue(json, fill);
293 }
294 
296 getJson(LedgerFill const& fill)
297 {
298  Json::Value json;
299  fillJson(json, fill);
300  return json;
301 }
302 
303 } // namespace ripple
ripple::STTx::getTxnType
TxType getTxnType() const
Definition: STTx.h:179
Json::appendObject
Json::Value & appendObject(Json::Value &)
Append a new subobject to a Json object.
Definition: Object.h:450
ripple::LedgerFill::dumpTxrp
@ dumpTxrp
Definition: LedgerToJson.h:46
std::shared_ptr
STL class.
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:176
std::exception
STL class.
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s, bool includeHash)
Definition: View.cpp:162
ripple::LedgerFill::dumpQueue
@ dumpQueue
Definition: LedgerToJson.h:52
ripple::transToken
std::string transToken(TER code)
Definition: TER.cpp:210
ripple::LedgerFill::expand
@ expand
Definition: LedgerToJson.h:48
Json::copyFrom
void copyFrom(Json::Value &to, Json::Value const &from)
Copy all the keys and values from one object into another.
Definition: Object.cpp:226
std::fill
T fill(T... args)
ripple::ttPAYMENT
@ ttPAYMENT
This transaction type executes a payment.
Definition: TxFormats.h:59
ripple::serializeHex
std::string serializeHex(STObject const &o)
Serialize an object to a hex string.
Definition: LedgerToJson.h:85
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::STObject::getAccountID
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:589
ripple::JsonOptions::none
@ none
ripple::LedgerFill::full
@ full
Definition: LedgerToJson.h:49
ripple::sfTakerGets
const SF_AMOUNT sfTakerGets
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::STTx::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STTx.cpp:229
ripple::accountFunds
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition: View.cpp:267
ripple::ttOFFER_CREATE
@ ttOFFER_CREATE
This transaction type creates an offer to trade one asset for another.
Definition: TxFormats.h:80
ripple::STTx::getTransactionID
uint256 getTransactionID() const
Definition: STTx.h:191
Json::setArray
Json::Value & setArray(Json::Value &, Json::StaticString const &key)
Add a new subarray at a named key in a Json object.
Definition: Object.h:414
ripple::LedgerFill::binary
@ binary
Definition: LedgerToJson.h:50
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:296
ripple::getCloseAgree
bool getCloseAgree(LedgerInfo const &info)
Definition: ReadView.h:351
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerFill::ownerFunds
@ ownerFunds
Definition: LedgerToJson.h:51
Json::addObject
Json::Value & addObject(Json::Value &, Json::StaticString const &key)
Add a new subobject at a named key in a Json object.
Definition: Object.h:426
ripple::RPC::insertDeliveredAmount
void insertDeliveredAmount(Json::Value &meta, ReadView const &, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &)
Add a delivered_amount field to the meta input/output parameter.
Definition: DeliveredAmount.cpp:143
ripple::ttCHECK_CASH
@ ttCHECK_CASH
This transaction type cashes an existing check.
Definition: TxFormats.h:110
ripple::addJson
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Object or Json::Value with a description of the ledger.
Definition: LedgerToJson.cpp:286
ripple::fhIGNORE_FREEZE
@ fhIGNORE_FREEZE
Definition: View.h:76
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::LedgerFill::dumpState
@ dumpState
Definition: LedgerToJson.h:47
ripple::STObject::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STObject.cpp:725
ripple::LedgerFill
Definition: LedgerToJson.h:33
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:56
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:603
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::flatFetchTransactions
std::vector< std::pair< std::shared_ptr< STTx const >, std::shared_ptr< STObject const > > > flatFetchTransactions(Application &app, std::vector< uint256 > &nodestoreHashes)
Definition: Ledger.cpp:1151