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/misc/TxQ.h>
22 #include <ripple/basics/base_uint.h>
23 #include <ripple/rpc/Context.h>
24 #include <ripple/rpc/DeliveredAmount.h>
25 
26 #include <date/date.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  for (auto& i : fill.ledger.txs)
179  {
180  txns.append(
181  fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
182  }
183  }
184  catch (std::exception const&)
185  {
186  // Nothing the user can do about this.
187  }
188 }
189 
190 template <class Object>
191 void
192 fillJsonState(Object& json, LedgerFill const& fill)
193 {
194  auto& ledger = fill.ledger;
195  auto&& array = Json::setArray(json, jss::accountState);
196  auto expanded = isExpanded(fill);
197  auto binary = isBinary(fill);
198 
199  for (auto const& sle : ledger.sles)
200  {
201  if (fill.type == ltINVALID || sle->getType() == fill.type)
202  {
203  if (binary)
204  {
205  auto&& obj = appendObject(array);
206  obj[jss::hash] = to_string(sle->key());
207  obj[jss::tx_blob] = serializeHex(*sle);
208  }
209  else if (expanded)
210  array.append(sle->getJson(JsonOptions::none));
211  else
212  array.append(to_string(sle->key()));
213  }
214  }
215 }
216 
217 template <class Object>
218 void
219 fillJsonQueue(Object& json, LedgerFill const& fill)
220 {
221  auto&& queueData = Json::setArray(json, jss::queue_data);
222  auto bBinary = isBinary(fill);
223  auto bExpanded = isExpanded(fill);
224 
225  for (auto const& tx : fill.txQueue)
226  {
227  auto&& txJson = appendObject(queueData);
228  txJson[jss::fee_level] = to_string(tx.feeLevel);
229  if (tx.lastValid)
230  txJson[jss::LastLedgerSequence] = *tx.lastValid;
231 
232  txJson[jss::fee] = to_string(tx.consequences.fee());
233  auto const spend =
234  tx.consequences.potentialSpend() + tx.consequences.fee();
235  txJson[jss::max_spend_drops] = to_string(spend);
236  txJson[jss::auth_change] = tx.consequences.isBlocker();
237 
238  txJson[jss::account] = to_string(tx.account);
239  txJson["retries_remaining"] = tx.retriesRemaining;
240  txJson["preflight_result"] = transToken(tx.preflightResult);
241  if (tx.lastResult)
242  txJson["last_result"] = transToken(*tx.lastResult);
243 
244  txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded, tx.txn, nullptr);
245  }
246 }
247 
248 template <class Object>
249 void
250 fillJson(Object& json, LedgerFill const& fill)
251 {
252  // TODO: what happens if bBinary and bExtracted are both set?
253  // Is there a way to report this back?
254  auto bFull = isFull(fill);
255  if (isBinary(fill))
256  fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info());
257  else
258  fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
259 
260  if (bFull || fill.options & LedgerFill::dumpTxrp)
261  fillJsonTx(json, fill);
262 
263  if (bFull || fill.options & LedgerFill::dumpState)
264  fillJsonState(json, fill);
265 }
266 
267 } // namespace
268 
269 void
270 addJson(Json::Value& json, LedgerFill const& fill)
271 {
272  auto&& object = Json::addObject(json, jss::ledger);
273  fillJson(object, fill);
274 
275  if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty())
276  fillJsonQueue(json, fill);
277 }
278 
280 getJson(LedgerFill const& fill)
281 {
282  Json::Value json;
283  fillJson(json, fill);
284  return json;
285 }
286 
287 } // 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:44
std::shared_ptr
STL class.
std::exception
STL class.
ripple::ttOFFER_CREATE
@ ttOFFER_CREATE
Definition: TxFormats.h:43
ripple::LedgerFill::dumpQueue
@ dumpQueue
Definition: LedgerToJson.h:50
ripple::transToken
std::string transToken(TER code)
Definition: TER.cpp:195
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s)
Definition: View.cpp:43
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
ripple::LedgerFill::expand
@ expand
Definition: LedgerToJson.h:46
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:82
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:47
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:136
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:48
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:280
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:49
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:133
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:270
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:45
ripple::STObject::getJson
virtual Json::Value getJson(JsonOptions options) const override
Definition: STObject.cpp:698
ripple::LedgerFill
Definition: LedgerToJson.h:32
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:54
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