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 
57  if (closed)
58  {
59  json[jss::closed] = true;
60  }
61  else if (!bFull)
62  {
63  json[jss::closed] = false;
64  return;
65  }
66 
67  json[jss::ledger_hash] = to_string(info.hash);
68  json[jss::transaction_hash] = to_string(info.txHash);
69  json[jss::account_hash] = to_string(info.accountHash);
70  json[jss::total_coins] = to_string(info.drops);
71 
72  json[jss::close_flags] = info.closeFlags;
73 
74  // Always show fields that contribute to the ledger hash
75  json[jss::parent_close_time] =
76  info.parentCloseTime.time_since_epoch().count();
77  json[jss::close_time] = info.closeTime.time_since_epoch().count();
78  json[jss::close_time_resolution] = info.closeTimeResolution.count();
79 
80  if (info.closeTime != NetClock::time_point{})
81  {
82  json[jss::close_time_human] = to_string(info.closeTime);
83  if (!getCloseAgree(info))
84  json[jss::close_time_estimated] = true;
85  }
86 }
87 
88 template <class Object>
89 void
90 fillJsonBinary(Object& json, bool closed, LedgerInfo const& info)
91 {
92  if (!closed)
93  json[jss::closed] = false;
94  else
95  {
96  json[jss::closed] = true;
97 
98  Serializer s;
99  addRaw(info, s);
100  json[jss::ledger_data] = strHex(s.peekData());
101  }
102 }
103 
105 fillJsonTx(
106  LedgerFill const& fill,
107  bool bBinary,
108  bool bExpanded,
109  std::shared_ptr<STTx const> const& txn,
110  std::shared_ptr<STObject const> const& stMeta)
111 {
112  if (!bExpanded)
113  return to_string(txn->getTransactionID());
114 
116  auto const txnType = txn->getTxnType();
117  if (bBinary)
118  {
119  txJson[jss::tx_blob] = serializeHex(*txn);
120  if (stMeta)
121  txJson[jss::meta] = serializeHex(*stMeta);
122  }
123  else
124  {
125  copyFrom(txJson, txn->getJson(JsonOptions::none));
126  if (stMeta)
127  {
128  txJson[jss::metaData] = stMeta->getJson(JsonOptions::none);
129 
130  // If applicable, insert delivered amount
131  if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
133  txJson[jss::metaData],
134  fill.ledger,
135  txn,
136  {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
137  }
138  }
139 
140  if ((fill.options & LedgerFill::ownerFunds) &&
141  txn->getTxnType() == ttOFFER_CREATE)
142  {
143  auto const account = txn->getAccountID(sfAccount);
144  auto const amount = txn->getFieldAmount(sfTakerGets);
145 
146  // If the offer create is not self funded then add the
147  // owner balance
148  if (account != amount.getIssuer())
149  {
150  auto const ownerFunds = accountFunds(
151  fill.ledger,
152  account,
153  amount,
155  beast::Journal{beast::Journal::getNullSink()});
156  txJson[jss::owner_funds] = ownerFunds.getText();
157  }
158  }
159 
160  return txJson;
161 }
162 
163 template <class Object>
164 void
165 fillJsonTx(Object& json, LedgerFill const& fill)
166 {
167  auto&& txns = setArray(json, jss::transactions);
168  auto bBinary = isBinary(fill);
169  auto bExpanded = isExpanded(fill);
170 
171  try
172  {
173  auto appendAll = [&](auto const& txs) {
174  for (auto& i : txs)
175  {
176  txns.append(
177  fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
178  }
179  };
180 
181  if (fill.context && fill.context->app.config().reporting())
182  {
183  appendAll(flatFetchTransactions(fill.ledger, fill.context->app));
184  }
185  else
186  {
187  appendAll(fill.ledger.txs);
188  }
189  }
190  catch (std::exception const& ex)
191  {
192  // Nothing the user can do about this.
193  if (fill.context)
194  {
195  JLOG(fill.context->j.error())
196  << "Exception in " << __func__ << ": " << ex.what();
197  }
198  }
199 }
200 
201 template <class Object>
202 void
203 fillJsonState(Object& json, LedgerFill const& fill)
204 {
205  auto& ledger = fill.ledger;
206  auto&& array = Json::setArray(json, jss::accountState);
207  auto expanded = isExpanded(fill);
208  auto binary = isBinary(fill);
209 
210  for (auto const& sle : ledger.sles)
211  {
212  if (fill.type == ltANY || sle->getType() == fill.type)
213  {
214  if (binary)
215  {
216  auto&& obj = appendObject(array);
217  obj[jss::hash] = to_string(sle->key());
218  obj[jss::tx_blob] = serializeHex(*sle);
219  }
220  else if (expanded)
221  array.append(sle->getJson(JsonOptions::none));
222  else
223  array.append(to_string(sle->key()));
224  }
225  }
226 }
227 
228 template <class Object>
229 void
230 fillJsonQueue(Object& json, LedgerFill const& fill)
231 {
232  auto&& queueData = Json::setArray(json, jss::queue_data);
233  auto bBinary = isBinary(fill);
234  auto bExpanded = isExpanded(fill);
235 
236  for (auto const& tx : fill.txQueue)
237  {
238  auto&& txJson = appendObject(queueData);
239  txJson[jss::fee_level] = to_string(tx.feeLevel);
240  if (tx.lastValid)
241  txJson[jss::LastLedgerSequence] = *tx.lastValid;
242 
243  txJson[jss::fee] = to_string(tx.consequences.fee());
244  auto const spend =
245  tx.consequences.potentialSpend() + tx.consequences.fee();
246  txJson[jss::max_spend_drops] = to_string(spend);
247  txJson[jss::auth_change] = tx.consequences.isBlocker();
248 
249  txJson[jss::account] = to_string(tx.account);
250  txJson["retries_remaining"] = tx.retriesRemaining;
251  txJson["preflight_result"] = transToken(tx.preflightResult);
252  if (tx.lastResult)
253  txJson["last_result"] = transToken(*tx.lastResult);
254 
255  txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded, tx.txn, nullptr);
256  }
257 }
258 
259 template <class Object>
260 void
261 fillJson(Object& json, LedgerFill const& fill)
262 {
263  // TODO: what happens if bBinary and bExtracted are both set?
264  // Is there a way to report this back?
265  auto bFull = isFull(fill);
266  if (isBinary(fill))
267  fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info());
268  else
269  fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
270 
271  if (bFull || fill.options & LedgerFill::dumpTxrp)
272  fillJsonTx(json, fill);
273 
274  if (bFull || fill.options & LedgerFill::dumpState)
275  fillJsonState(json, fill);
276 }
277 
278 } // namespace
279 
280 void
281 addJson(Json::Value& json, LedgerFill const& fill)
282 {
283  auto&& object = Json::addObject(json, jss::ledger);
284  fillJson(object, fill);
285 
286  if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty())
287  fillJsonQueue(json, fill);
288 }
289 
291 getJson(LedgerFill const& fill)
292 {
293  Json::Value json;
294  fillJson(json, fill);
295  return json;
296 }
297 
298 } // 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:291
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:281
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