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