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  if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
135  {
136  // Insert delivered amount
137  auto txMeta = std::make_shared<TxMeta>(
138  txn->getTransactionID(), fill.ledger.seq(), *stMeta);
140  txJson[jss::metaData], fill.ledger, txn, *txMeta);
141  }
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&)
196  {
197  // Nothing the user can do about this.
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:207
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
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:1120