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  if (tx.consequences)
232  {
233  txJson[jss::fee] = to_string(tx.consequences->fee);
234  auto spend = tx.consequences->potentialSpend + tx.consequences->fee;
235  txJson[jss::max_spend_drops] = to_string(spend);
236  auto authChanged =
237  tx.consequences->category == TxConsequences::blocker;
238  txJson[jss::auth_change] = authChanged;
239  }
240 
241  txJson[jss::account] = to_string(tx.account);
242  txJson["retries_remaining"] = tx.retriesRemaining;
243  txJson["preflight_result"] = transToken(tx.preflightResult);
244  if (tx.lastResult)
245  txJson["last_result"] = transToken(*tx.lastResult);
246 
247  txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded, tx.txn, nullptr);
248  }
249 }
250 
251 template <class Object>
252 void
253 fillJson(Object& json, LedgerFill const& fill)
254 {
255  // TODO: what happens if bBinary and bExtracted are both set?
256  // Is there a way to report this back?
257  auto bFull = isFull(fill);
258  if (isBinary(fill))
259  fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info());
260  else
261  fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
262 
263  if (bFull || fill.options & LedgerFill::dumpTxrp)
264  fillJsonTx(json, fill);
265 
266  if (bFull || fill.options & LedgerFill::dumpState)
267  fillJsonState(json, fill);
268 }
269 
270 } // namespace
271 
272 void
273 addJson(Json::Value& json, LedgerFill const& fill)
274 {
275  auto&& object = Json::addObject(json, jss::ledger);
276  fillJson(object, fill);
277 
278  if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty())
279  fillJsonQueue(json, fill);
280 }
281 
283 getJson(LedgerFill const& fill)
284 {
285  Json::Value json;
286  fillJson(json, fill);
287  return json;
288 }
289 
290 } // namespace ripple
ripple::STTx::getTxnType
TxType getTxnType() const
Definition: STTx.h:105
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::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
ripple::transToken
std::string transToken(TER code)
Definition: TER.cpp:193
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:42
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
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:194
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:131
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:283
ripple::getCloseAgree
bool getCloseAgree(LedgerInfo const &info)
Definition: ReadView.h:414
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:273
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:444
ripple::fhIGNORE_FREEZE
@ fhIGNORE_FREEZE
Definition: View.h:53
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
ripple::LedgerFill::dumpState
@ dumpState
Definition: LedgerToJson.h:45
ripple::TxConsequences::blocker
@ blocker
Affects the ability of subsequent transactions to claim a fee.
Definition: applySteps.h:135
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