rippled
STParsedJSON.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/basics/StringUtilities.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/safe_cast.h>
23 #include <ripple/beast/core/LexicalCast.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/LedgerFormats.h>
26 #include <ripple/protocol/STAccount.h>
27 #include <ripple/protocol/STAmount.h>
28 #include <ripple/protocol/STArray.h>
29 #include <ripple/protocol/STBitString.h>
30 #include <ripple/protocol/STBlob.h>
31 #include <ripple/protocol/STInteger.h>
32 #include <ripple/protocol/STParsedJSON.h>
33 #include <ripple/protocol/STPathSet.h>
34 #include <ripple/protocol/STVector256.h>
35 #include <ripple/protocol/TER.h>
36 #include <ripple/protocol/TxFormats.h>
37 #include <ripple/protocol/UintTypes.h>
38 #include <ripple/protocol/impl/STVar.h>
39 #include <cassert>
40 #include <charconv>
41 #include <memory>
42 
43 namespace ripple {
44 
45 namespace STParsedJSONDetail {
46 template <typename U, typename S>
47 constexpr std::
48  enable_if_t<std::is_unsigned<U>::value && std::is_signed<S>::value, U>
49  to_unsigned(S value)
50 {
51  if (value < 0 || std::numeric_limits<U>::max() < value)
52  Throw<std::runtime_error>("Value out of range");
53  return static_cast<U>(value);
54 }
55 
56 template <typename U1, typename U2>
57 constexpr std::
58  enable_if_t<std::is_unsigned<U1>::value && std::is_unsigned<U2>::value, U1>
59  to_unsigned(U2 value)
60 {
61  if (std::numeric_limits<U1>::max() < value)
62  Throw<std::runtime_error>("Value out of range");
63  return static_cast<U1>(value);
64 }
65 
66 static std::string
67 make_name(std::string const& object, std::string const& field)
68 {
69  if (field.empty())
70  return object;
71 
72  return object + "." + field;
73 }
74 
75 static Json::Value
76 not_an_object(std::string const& object, std::string const& field)
77 {
78  return RPC::make_error(
80  "Field '" + make_name(object, field) + "' is not a JSON object.");
81 }
82 
83 static Json::Value
84 not_an_object(std::string const& object)
85 {
86  return not_an_object(object, "");
87 }
88 
89 static Json::Value
90 not_an_array(std::string const& object)
91 {
92  return RPC::make_error(
93  rpcINVALID_PARAMS, "Field '" + object + "' is not a JSON array.");
94 }
95 
96 static Json::Value
97 unknown_field(std::string const& object, std::string const& field)
98 {
99  return RPC::make_error(
101  "Field '" + make_name(object, field) + "' is unknown.");
102 }
103 
104 static Json::Value
105 out_of_range(std::string const& object, std::string const& field)
106 {
107  return RPC::make_error(
109  "Field '" + make_name(object, field) + "' is out of range.");
110 }
111 
112 static Json::Value
113 bad_type(std::string const& object, std::string const& field)
114 {
115  return RPC::make_error(
117  "Field '" + make_name(object, field) + "' has bad type.");
118 }
119 
120 static Json::Value
121 invalid_data(std::string const& object, std::string const& field)
122 {
123  return RPC::make_error(
125  "Field '" + make_name(object, field) + "' has invalid data.");
126 }
127 
128 static Json::Value
129 invalid_data(std::string const& object)
130 {
131  return invalid_data(object, "");
132 }
133 
134 static Json::Value
135 array_expected(std::string const& object, std::string const& field)
136 {
137  return RPC::make_error(
139  "Field '" + make_name(object, field) + "' must be a JSON array.");
140 }
141 
142 static Json::Value
143 string_expected(std::string const& object, std::string const& field)
144 {
145  return RPC::make_error(
147  "Field '" + make_name(object, field) + "' must be a string.");
148 }
149 
150 static Json::Value
151 too_deep(std::string const& object)
152 {
153  return RPC::make_error(
155  "Field '" + object + "' exceeds nesting depth limit.");
156 }
157 
158 static Json::Value
159 singleton_expected(std::string const& object, unsigned int index)
160 {
161  return RPC::make_error(
163  "Field '" + object + "[" + std::to_string(index) +
164  "]' must be an object with a single key/object value.");
165 }
166 
167 static Json::Value
168 template_mismatch(SField const& sField)
169 {
170  return RPC::make_error(
172  "Object '" + sField.getName() +
173  "' contents did not meet requirements for that type.");
174 }
175 
176 static Json::Value
178 {
179  return RPC::make_error(
181  "Item '" + item + "' at index " + std::to_string(index) +
182  " is not an object. Arrays may only contain objects.");
183 }
184 
185 // This function is used by parseObject to parse any JSON type that doesn't
186 // recurse. Everything represented here is a leaf-type.
189  std::string const& json_name,
190  std::string const& fieldName,
191  SField const* name,
192  Json::Value const& value,
193  Json::Value& error)
194 {
196 
197  auto const& field = SField::getField(fieldName);
198 
199  if (field == sfInvalid)
200  {
201  error = unknown_field(json_name, fieldName);
202  return ret;
203  }
204 
205  switch (field.fieldType)
206  {
207  case STI_UINT8:
208  try
209  {
210  constexpr auto minValue =
212  constexpr auto maxValue =
214  if (value.isString())
215  {
216  std::string const strValue = value.asString();
217 
218  if (!strValue.empty() &&
219  ((strValue[0] < '0') || (strValue[0] > '9')))
220  {
221  if (field == sfTransactionResult)
222  {
223  auto ter = transCode(strValue);
224 
225  if (!ter || TERtoInt(*ter) < minValue ||
226  TERtoInt(*ter) > maxValue)
227  {
228  error = out_of_range(json_name, fieldName);
229  return ret;
230  }
231 
232  ret = detail::make_stvar<STUInt8>(
233  field,
234  static_cast<std::uint8_t>(TERtoInt(*ter)));
235  }
236  else
237  {
238  error = bad_type(json_name, fieldName);
239  return ret;
240  }
241  }
242  else
243  {
244  ret = detail::make_stvar<STUInt8>(
245  field,
246  beast::lexicalCastThrow<std::uint8_t>(strValue));
247  }
248  }
249  else if (value.isInt())
250  {
251  if (value.asInt() < minValue || value.asInt() > maxValue)
252  {
253  error = out_of_range(json_name, fieldName);
254  return ret;
255  }
256 
257  ret = detail::make_stvar<STUInt8>(
258  field, static_cast<std::uint8_t>(value.asInt()));
259  }
260  else if (value.isUInt())
261  {
262  if (value.asUInt() > maxValue)
263  {
264  error = out_of_range(json_name, fieldName);
265  return ret;
266  }
267 
268  ret = detail::make_stvar<STUInt8>(
269  field, static_cast<std::uint8_t>(value.asUInt()));
270  }
271  else
272  {
273  error = bad_type(json_name, fieldName);
274  return ret;
275  }
276  }
277  catch (std::exception const&)
278  {
279  error = invalid_data(json_name, fieldName);
280  return ret;
281  }
282  break;
283 
284  case STI_UINT16:
285  try
286  {
287  if (value.isString())
288  {
289  std::string const strValue = value.asString();
290 
291  if (!strValue.empty() &&
292  ((strValue[0] < '0') || (strValue[0] > '9')))
293  {
294  if (field == sfTransactionType)
295  {
296  ret = detail::make_stvar<STUInt16>(
297  field,
298  static_cast<std::uint16_t>(
299  TxFormats::getInstance().findTypeByName(
300  strValue)));
301 
302  if (*name == sfGeneric)
303  name = &sfTransaction;
304  }
305  else if (field == sfLedgerEntryType)
306  {
307  ret = detail::make_stvar<STUInt16>(
308  field,
309  static_cast<std::uint16_t>(
310  LedgerFormats::getInstance().findTypeByName(
311  strValue)));
312 
313  if (*name == sfGeneric)
314  name = &sfLedgerEntry;
315  }
316  else
317  {
318  error = invalid_data(json_name, fieldName);
319  return ret;
320  }
321  }
322  else
323  {
324  ret = detail::make_stvar<STUInt16>(
325  field,
326  beast::lexicalCastThrow<std::uint16_t>(strValue));
327  }
328  }
329  else if (value.isInt())
330  {
331  ret = detail::make_stvar<STUInt16>(
332  field, to_unsigned<std::uint16_t>(value.asInt()));
333  }
334  else if (value.isUInt())
335  {
336  ret = detail::make_stvar<STUInt16>(
337  field, to_unsigned<std::uint16_t>(value.asUInt()));
338  }
339  else
340  {
341  error = bad_type(json_name, fieldName);
342  return ret;
343  }
344  }
345  catch (std::exception const&)
346  {
347  error = invalid_data(json_name, fieldName);
348  return ret;
349  }
350 
351  break;
352 
353  case STI_UINT32:
354  try
355  {
356  if (value.isString())
357  {
358  ret = detail::make_stvar<STUInt32>(
359  field,
360  beast::lexicalCastThrow<std::uint32_t>(
361  value.asString()));
362  }
363  else if (value.isInt())
364  {
365  ret = detail::make_stvar<STUInt32>(
366  field, to_unsigned<std::uint32_t>(value.asInt()));
367  }
368  else if (value.isUInt())
369  {
370  ret = detail::make_stvar<STUInt32>(
371  field, safe_cast<std::uint32_t>(value.asUInt()));
372  }
373  else
374  {
375  error = bad_type(json_name, fieldName);
376  return ret;
377  }
378  }
379  catch (std::exception const&)
380  {
381  error = invalid_data(json_name, fieldName);
382  return ret;
383  }
384 
385  break;
386 
387  case STI_UINT64:
388  try
389  {
390  if (value.isString())
391  {
392  auto const str = value.asString();
393 
394  std::uint64_t val;
395 
396  auto [p, ec] = std::from_chars(
397  str.data(), str.data() + str.size(), val, 16);
398 
399  if (ec != std::errc() || (p != str.data() + str.size()))
400  Throw<std::invalid_argument>("invalid data");
401 
402  ret = detail::make_stvar<STUInt64>(field, val);
403  }
404  else if (value.isInt())
405  {
406  ret = detail::make_stvar<STUInt64>(
407  field, to_unsigned<std::uint64_t>(value.asInt()));
408  }
409  else if (value.isUInt())
410  {
411  ret = detail::make_stvar<STUInt64>(
412  field, safe_cast<std::uint64_t>(value.asUInt()));
413  }
414  else
415  {
416  error = bad_type(json_name, fieldName);
417  return ret;
418  }
419  }
420  catch (std::exception const&)
421  {
422  error = invalid_data(json_name, fieldName);
423  return ret;
424  }
425 
426  break;
427 
428  case STI_UINT128: {
429  if (!value.isString())
430  {
431  error = bad_type(json_name, fieldName);
432  return ret;
433  }
434 
435  uint128 num;
436 
437  if (auto const s = value.asString(); !num.parseHex(s))
438  {
439  if (!s.empty())
440  {
441  error = invalid_data(json_name, fieldName);
442  return ret;
443  }
444 
445  num.zero();
446  }
447 
448  ret = detail::make_stvar<STUInt128>(field, num);
449  break;
450  }
451 
452  case STI_UINT160: {
453  if (!value.isString())
454  {
455  error = bad_type(json_name, fieldName);
456  return ret;
457  }
458 
459  uint160 num;
460 
461  if (auto const s = value.asString(); !num.parseHex(s))
462  {
463  if (!s.empty())
464  {
465  error = invalid_data(json_name, fieldName);
466  return ret;
467  }
468 
469  num.zero();
470  }
471 
472  ret = detail::make_stvar<STUInt160>(field, num);
473  break;
474  }
475 
476  case STI_UINT256: {
477  if (!value.isString())
478  {
479  error = bad_type(json_name, fieldName);
480  return ret;
481  }
482 
483  uint256 num;
484 
485  if (auto const s = value.asString(); !num.parseHex(s))
486  {
487  if (!s.empty())
488  {
489  error = invalid_data(json_name, fieldName);
490  return ret;
491  }
492 
493  num.zero();
494  }
495 
496  ret = detail::make_stvar<STUInt256>(field, num);
497  break;
498  }
499 
500  case STI_VL:
501  if (!value.isString())
502  {
503  error = bad_type(json_name, fieldName);
504  return ret;
505  }
506 
507  try
508  {
509  if (auto vBlob = strUnHex(value.asString()))
510  {
511  ret = detail::make_stvar<STBlob>(
512  field, vBlob->data(), vBlob->size());
513  }
514  else
515  {
516  Throw<std::invalid_argument>("invalid data");
517  }
518  }
519  catch (std::exception const&)
520  {
521  error = invalid_data(json_name, fieldName);
522  return ret;
523  }
524 
525  break;
526 
527  case STI_AMOUNT:
528  try
529  {
530  ret =
531  detail::make_stvar<STAmount>(amountFromJson(field, value));
532  }
533  catch (std::exception const&)
534  {
535  error = invalid_data(json_name, fieldName);
536  return ret;
537  }
538 
539  break;
540 
541  case STI_VECTOR256:
542  if (!value.isArrayOrNull())
543  {
544  error = array_expected(json_name, fieldName);
545  return ret;
546  }
547 
548  try
549  {
550  STVector256 tail(field);
551  for (Json::UInt i = 0; value.isValidIndex(i); ++i)
552  {
553  uint256 s;
554  if (!s.parseHex(value[i].asString()))
555  Throw<std::invalid_argument>("invalid data");
556  tail.push_back(s);
557  }
558  ret = detail::make_stvar<STVector256>(std::move(tail));
559  }
560  catch (std::exception const&)
561  {
562  error = invalid_data(json_name, fieldName);
563  return ret;
564  }
565 
566  break;
567 
568  case STI_PATHSET:
569  if (!value.isArrayOrNull())
570  {
571  error = array_expected(json_name, fieldName);
572  return ret;
573  }
574 
575  try
576  {
577  STPathSet tail(field);
578 
579  for (Json::UInt i = 0; value.isValidIndex(i); ++i)
580  {
581  STPath p;
582 
583  if (!value[i].isArrayOrNull())
584  {
586  ss << fieldName << "[" << i << "]";
587  error = array_expected(json_name, ss.str());
588  return ret;
589  }
590 
591  for (Json::UInt j = 0; value[i].isValidIndex(j); ++j)
592  {
594  ss << fieldName << "[" << i << "][" << j << "]";
595  std::string const element_name(
596  json_name + "." + ss.str());
597 
598  // each element in this path has some combination of
599  // account, currency, or issuer
600 
601  Json::Value pathEl = value[i][j];
602 
603  if (!pathEl.isObject())
604  {
605  error = not_an_object(element_name);
606  return ret;
607  }
608 
609  Json::Value const& account = pathEl["account"];
610  Json::Value const& currency = pathEl["currency"];
611  Json::Value const& issuer = pathEl["issuer"];
612  bool hasCurrency = false;
613  AccountID uAccount, uIssuer;
614  Currency uCurrency;
615 
616  if (account)
617  {
618  // human account id
619  if (!account.isString())
620  {
621  error =
622  string_expected(element_name, "account");
623  return ret;
624  }
625 
626  // If we have what looks like a 160-bit hex value,
627  // we set it, otherwise, we assume it's an AccountID
628  if (!uAccount.parseHex(account.asString()))
629  {
630  auto const a =
631  parseBase58<AccountID>(account.asString());
632  if (!a)
633  {
634  error =
635  invalid_data(element_name, "account");
636  return ret;
637  }
638  uAccount = *a;
639  }
640  }
641 
642  if (currency)
643  {
644  // human currency
645  if (!currency.isString())
646  {
647  error =
648  string_expected(element_name, "currency");
649  return ret;
650  }
651 
652  hasCurrency = true;
653 
654  if (!uCurrency.parseHex(currency.asString()))
655  {
656  if (!to_currency(
657  uCurrency, currency.asString()))
658  {
659  error =
660  invalid_data(element_name, "currency");
661  return ret;
662  }
663  }
664  }
665 
666  if (issuer)
667  {
668  // human account id
669  if (!issuer.isString())
670  {
671  error = string_expected(element_name, "issuer");
672  return ret;
673  }
674 
675  if (!uIssuer.parseHex(issuer.asString()))
676  {
677  auto const a =
678  parseBase58<AccountID>(issuer.asString());
679  if (!a)
680  {
681  error =
682  invalid_data(element_name, "issuer");
683  return ret;
684  }
685  uIssuer = *a;
686  }
687  }
688 
689  p.emplace_back(
690  uAccount, uCurrency, uIssuer, hasCurrency);
691  }
692 
693  tail.push_back(p);
694  }
695  ret = detail::make_stvar<STPathSet>(std::move(tail));
696  }
697  catch (std::exception const&)
698  {
699  error = invalid_data(json_name, fieldName);
700  return ret;
701  }
702 
703  break;
704 
705  case STI_ACCOUNT: {
706  if (!value.isString())
707  {
708  error = bad_type(json_name, fieldName);
709  return ret;
710  }
711 
712  std::string const strValue = value.asString();
713 
714  try
715  {
716  if (AccountID account; account.parseHex(strValue))
717  return detail::make_stvar<STAccount>(field, account);
718 
719  if (auto result = parseBase58<AccountID>(strValue))
720  return detail::make_stvar<STAccount>(field, *result);
721 
722  error = invalid_data(json_name, fieldName);
723  return ret;
724  }
725  catch (std::exception const&)
726  {
727  error = invalid_data(json_name, fieldName);
728  return ret;
729  }
730  }
731  break;
732 
733  default:
734  error = bad_type(json_name, fieldName);
735  return ret;
736  }
737 
738  return ret;
739 }
740 
741 static const int maxDepth = 64;
742 
743 // Forward declaration since parseObject() and parseArray() call each other.
745 parseArray(
746  std::string const& json_name,
747  Json::Value const& json,
748  SField const& inName,
749  int depth,
750  Json::Value& error);
751 
754  std::string const& json_name,
755  Json::Value const& json,
756  SField const& inName,
757  int depth,
758  Json::Value& error)
759 {
760  if (!json.isObjectOrNull())
761  {
762  error = not_an_object(json_name);
763  return std::nullopt;
764  }
765 
766  if (depth > maxDepth)
767  {
768  error = too_deep(json_name);
769  return std::nullopt;
770  }
771 
772  try
773  {
774  STObject data(inName);
775 
776  for (auto const& fieldName : json.getMemberNames())
777  {
778  Json::Value const& value = json[fieldName];
779 
780  auto const& field = SField::getField(fieldName);
781 
782  if (field == sfInvalid)
783  {
784  error = unknown_field(json_name, fieldName);
785  return std::nullopt;
786  }
787 
788  switch (field.fieldType)
789  {
790  // Object-style containers (which recurse).
791  case STI_OBJECT:
792  case STI_TRANSACTION:
793  case STI_LEDGERENTRY:
794  case STI_VALIDATION:
795  if (!value.isObject())
796  {
797  error = not_an_object(json_name, fieldName);
798  return std::nullopt;
799  }
800 
801  try
802  {
803  auto ret = parseObject(
804  json_name + "." + fieldName,
805  value,
806  field,
807  depth + 1,
808  error);
809  if (!ret)
810  return std::nullopt;
811  data.emplace_back(std::move(*ret));
812  }
813  catch (std::exception const&)
814  {
815  error = invalid_data(json_name, fieldName);
816  return std::nullopt;
817  }
818 
819  break;
820 
821  // Array-style containers (which recurse).
822  case STI_ARRAY:
823  try
824  {
825  auto array = parseArray(
826  json_name + "." + fieldName,
827  value,
828  field,
829  depth + 1,
830  error);
831  if (!array.has_value())
832  return std::nullopt;
833  data.emplace_back(std::move(*array));
834  }
835  catch (std::exception const&)
836  {
837  error = invalid_data(json_name, fieldName);
838  return std::nullopt;
839  }
840 
841  break;
842 
843  // Everything else (types that don't recurse).
844  default: {
845  auto leaf =
846  parseLeaf(json_name, fieldName, &inName, value, error);
847 
848  if (!leaf)
849  return std::nullopt;
850 
851  data.emplace_back(std::move(*leaf));
852  }
853 
854  break;
855  }
856  }
857 
858  // Some inner object types have templates. Attempt to apply that.
859  data.applyTemplateFromSField(inName); // May throw
860 
861  return data;
862  }
863  catch (STObject::FieldErr const& e)
864  {
865  std::cerr << "template_mismatch: " << e.what() << "\n";
866  error = template_mismatch(inName);
867  }
868  catch (std::exception const&)
869  {
870  error = invalid_data(json_name);
871  }
872  return std::nullopt;
873 }
874 
877  std::string const& json_name,
878  Json::Value const& json,
879  SField const& inName,
880  int depth,
881  Json::Value& error)
882 {
883  if (!json.isArrayOrNull())
884  {
885  error = not_an_array(json_name);
886  return std::nullopt;
887  }
888 
889  if (depth > maxDepth)
890  {
891  error = too_deep(json_name);
892  return std::nullopt;
893  }
894 
895  try
896  {
897  STArray tail(inName);
898 
899  for (Json::UInt i = 0; json.isValidIndex(i); ++i)
900  {
901  bool const isObjectOrNull(json[i].isObjectOrNull());
902  bool const singleKey(isObjectOrNull ? json[i].size() == 1 : true);
903 
904  if (!isObjectOrNull || !singleKey)
905  {
906  // null values are !singleKey
907  error = singleton_expected(json_name, i);
908  return std::nullopt;
909  }
910 
911  // TODO: There doesn't seem to be a nice way to get just the
912  // first/only key in an object without copying all keys into
913  // a vector
914  std::string const objectName(json[i].getMemberNames()[0]);
915  ;
916  auto const& nameField(SField::getField(objectName));
917 
918  if (nameField == sfInvalid)
919  {
920  error = unknown_field(json_name, objectName);
921  return std::nullopt;
922  }
923 
924  Json::Value const objectFields(json[i][objectName]);
925 
927  ss << json_name << "."
928  << "[" << i << "]." << objectName;
929 
930  auto ret = parseObject(
931  ss.str(), objectFields, nameField, depth + 1, error);
932  if (!ret)
933  {
934  std::string errMsg = error["error_message"].asString();
935  error["error_message"] =
936  "Error at '" + ss.str() + "'. " + errMsg;
937  return std::nullopt;
938  }
939 
940  if (ret->getFName().fieldType != STI_OBJECT)
941  {
942  error = non_object_in_array(ss.str(), i);
943  return std::nullopt;
944  }
945 
946  tail.push_back(std::move(*ret));
947  }
948 
949  return detail::make_stvar<STArray>(std::move(tail));
950  }
951  catch (std::exception const&)
952  {
953  error = invalid_data(json_name);
954  return std::nullopt;
955  }
956 }
957 
958 } // namespace STParsedJSONDetail
959 
960 //------------------------------------------------------------------------------
961 
963  std::string const& name,
964  Json::Value const& json)
965 {
966  using namespace STParsedJSONDetail;
967  object = parseObject(name, json, sfGeneric, 0, error);
968 }
969 
970 //------------------------------------------------------------------------------
971 
973  std::string const& name,
974  Json::Value const& json)
975 {
976  using namespace STParsedJSONDetail;
977  auto arr = parseArray(name, json, sfGeneric, 0, error);
978  if (!arr)
979  array.reset();
980  else
981  {
982  auto p = dynamic_cast<STArray*>(&arr->get());
983  if (p == nullptr)
984  array.reset();
985  else
986  array = std::move(*p);
987  }
988 }
989 
990 } // namespace ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:979
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:80
std::is_signed
ripple::STParsedJSONDetail::maxDepth
static const int maxDepth
Definition: STParsedJSON.cpp:741
ripple::STParsedJSONDetail::singleton_expected
static Json::Value singleton_expected(std::string const &object, unsigned int index)
Definition: STParsedJSON.cpp:159
std::is_unsigned
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
std::string
STL class.
ripple::STI_UINT128
@ STI_UINT128
Definition: SField.h:61
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
Json::Value::isValidIndex
bool isValidIndex(UInt index) const
Return true if index < size().
Definition: json_value.cpp:841
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:327
ripple::STParsedJSONDetail::template_mismatch
static Json::Value template_mismatch(SField const &sField)
Definition: STParsedJSON.cpp:168
ripple::STParsedJSONDetail::bad_type
static Json::Value bad_type(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:113
charconv
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
ripple::STI_AMOUNT
@ STI_AMOUNT
Definition: SField.h:63
ripple::STI_UINT8
@ STI_UINT8
Definition: SField.h:71
ripple::STI_PATHSET
@ STI_PATHSET
Definition: SField.h:73
ripple::STParsedJSONDetail::parseArray
static std::optional< detail::STVar > parseArray(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:876
ripple::STVector256::push_back
void push_back(uint256 const &v)
Definition: STVector256.h:216
ripple::STI_VALIDATION
@ STI_VALIDATION
Definition: SField.h:84
ripple::STI_LEDGERENTRY
@ STI_LEDGERENTRY
Definition: SField.h:83
ripple::STParsedJSONDetail::non_object_in_array
static Json::Value non_object_in_array(std::string const &item, Json::UInt index)
Definition: STParsedJSON.cpp:177
std::stringstream
STL class.
ripple::STI_UINT160
@ STI_UINT160
Definition: SField.h:72
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:212
ripple::STParsedJSONDetail::too_deep
static Json::Value too_deep(std::string const &object)
Definition: STParsedJSON.cpp:151
std::cerr
ripple::SField::getField
static const SField & getField(int fieldCode)
Definition: SField.cpp:387
ripple::STI_ACCOUNT
@ STI_ACCOUNT
Definition: SField.h:65
ripple::STI_ARRAY
@ STI_ARRAY
Definition: SField.h:68
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:301
ripple::sfInvalid
const SField sfInvalid(access, -1)
Definition: SField.h:326
ripple::STPathSet
Definition: STPathSet.h:176
ripple::STParsedJSONDetail::parseLeaf
static std::optional< detail::STVar > parseLeaf(std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
Definition: STParsedJSON.cpp:188
ripple::transCode
std::optional< TER > transCode(std::string const &token)
Definition: TER.cpp:228
ripple::STParsedJSONObject::error
Json::Value error
On failure, an appropriate set of error values.
Definition: STParsedJSON.h:53
ripple::sfLedgerEntry
const SField sfLedgerEntry
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
ripple::sfTransactionType
const SF_UINT16 sfTransactionType
ripple::STObject::FieldErr
Definition: STObject.h:643
ripple::STParsedJSONDetail::out_of_range
static Json::Value out_of_range(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:105
ripple::TxFormats::getInstance
static TxFormats const & getInstance()
Definition: TxFormats.cpp:334
Json::Value::isArrayOrNull
bool isArrayOrNull() const
Definition: json_value.cpp:1021
ripple::STArray
Definition: STArray.h:28
std::to_string
T to_string(T... args)
ripple::STI_VL
@ STI_VL
Definition: SField.h:64
ripple::STI_UINT16
@ STI_UINT16
Definition: SField.h:58
ripple::STPath::emplace_back
void emplace_back(Args &&... args)
Definition: STPathSet.h:412
std::errc
ripple::amountFromJson
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition: STAmount.cpp:929
std::uint8_t
ripple::STI_VECTOR256
@ STI_VECTOR256
Definition: SField.h:74
std::from_chars
T from_chars(T... args)
ripple::STParsedJSONDetail::to_unsigned
constexpr std::enable_if_t< std::is_unsigned< U >::value &&std::is_signed< S >::value, U > to_unsigned(S value)
Definition: STParsedJSON.cpp:49
memory
ripple::LedgerFormats::getInstance
static LedgerFormats const & getInstance()
Definition: LedgerFormats.cpp:274
std::numeric_limits::min
T min(T... args)
ripple::STI_UINT32
@ STI_UINT32
Definition: SField.h:59
ripple::STObject
Definition: STObject.h:51
ripple::STParsedJSONArray::STParsedJSONArray
STParsedJSONArray()=delete
Json::Value::getMemberNames
Members getMemberNames() const
Return a list of the member names.
Definition: json_value.cpp:948
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sfTransactionResult
const SF_UINT8 sfTransactionResult
ripple::sfLedgerEntryType
const SF_UINT16 sfLedgerEntryType
ripple::STParsedJSONDetail::parseObject
static std::optional< STObject > parseObject(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:753
ripple::SField
Identifies fields.
Definition: SField.h:112
ripple::STI_UINT64
@ STI_UINT64
Definition: SField.h:60
ripple::base_uint::zero
void zero()
Definition: base_uint.h:542
ripple::SField::getName
std::string const & getName() const
Definition: SField.h:175
ripple::STParsedJSONDetail::not_an_object
static Json::Value not_an_object(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:76
cassert
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:545
Json::Value::isUInt
bool isUInt() const
Definition: json_value.cpp:985
ripple::STParsedJSONDetail::make_name
static std::string make_name(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:67
ripple::STVector256
Definition: STVector256.h:29
ripple::STParsedJSONDetail::invalid_data
static Json::Value invalid_data(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:121
std::string::empty
T empty(T... args)
std::optional
std::stringstream::str
T str(T... args)
Json::Value::asInt
Int asInt() const
Definition: json_value.cpp:503
ripple::STParsedJSONObject::STParsedJSONObject
STParsedJSONObject()=delete
ripple::STParsedJSONDetail::string_expected
static Json::Value string_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:143
ripple::STI_OBJECT
@ STI_OBJECT
Definition: SField.h:67
std::numeric_limits::max
T max(T... args)
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::STPath
Definition: STPathSet.h:118
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:50
ripple::STI_UINT256
@ STI_UINT256
Definition: SField.h:62
std::numeric_limits
Json::Value::isObjectOrNull
bool isObjectOrNull() const
Definition: json_value.cpp:1033
ripple::sfTransaction
const SField sfTransaction
ripple::STParsedJSONDetail::array_expected
static Json::Value array_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:135
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:178
std::runtime_error::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::STParsedJSONDetail::not_an_array
static Json::Value not_an_array(std::string const &object)
Definition: STParsedJSON.cpp:90
ripple::STI_TRANSACTION
@ STI_TRANSACTION
Definition: SField.h:82
ripple::STParsedJSONDetail::unknown_field
static Json::Value unknown_field(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:97
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
ripple::STPathSet::push_back
void push_back(STPath const &e)
Definition: STPathSet.h:509