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