Monero
json_object.h
Go to the documentation of this file.
1 // Copyright (c) 2016-2020, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #pragma once
30 
31 #include <boost/utility/string_ref.hpp>
32 #include <cstring>
33 #include <rapidjson/document.h>
34 #include <rapidjson/writer.h>
35 #include <vector>
36 
37 #include "byte_stream.h"
41 #include "common/sfinae_helpers.h"
42 #include "hex.h"
43 #include "span.h"
44 
45 #define OBJECT_HAS_MEMBER_OR_THROW(val, key) \
46  do \
47  { \
48  if (!val.HasMember(key)) \
49  { \
50  throw cryptonote::json::MISSING_KEY(key); \
51  } \
52  } while (0);
53 
54 #define INSERT_INTO_JSON_OBJECT(dest, key, source) \
55  dest.Key(#key, sizeof(#key) - 1); \
56  cryptonote::json::toJsonValue(dest, source);
57 
58 #define GET_FROM_JSON_OBJECT(source, dst, key) \
59  OBJECT_HAS_MEMBER_OR_THROW(source, #key) \
60  decltype(dst) dstVal##key; \
61  cryptonote::json::fromJsonValue(source[#key], dstVal##key); \
62  dst = dstVal##key;
63 
64 namespace cryptonote
65 {
66 
67 namespace json
68 {
69 
70 struct JSON_ERROR : public std::exception
71 {
72  protected:
73  JSON_ERROR() { }
74  std::string m;
75 
76  public:
77  virtual ~JSON_ERROR() { }
78 
79  const char* what() const throw()
80  {
81  return m.c_str();
82  }
83 };
84 
85 struct MISSING_KEY : public JSON_ERROR
86 {
87  MISSING_KEY(const char* key)
88  {
89  m = std::string("Key \"") + key + "\" missing from object.";
90  }
91 };
92 
93 struct WRONG_TYPE : public JSON_ERROR
94 {
95  WRONG_TYPE(const char* type)
96  {
97  m = std::string("Json value has incorrect type, expected: ") + type;
98  }
99 };
100 
101 struct BAD_INPUT : public JSON_ERROR
102 {
104  {
105  m = "An item failed to convert from json object to native object";
106  }
107 };
108 
109 struct PARSE_FAIL : public JSON_ERROR
110 {
112  {
113  m = "Failed to parse the json request";
114  }
115 };
116 
117 template<typename Type>
118 inline constexpr bool is_to_hex()
119 {
120  return std::is_pod<Type>() && !std::is_integral<Type>();
121 }
122 
123 void read_hex(const rapidjson::Value& val, epee::span<std::uint8_t> dest);
124 
125 // POD to json key
126 template <class Type>
127 inline typename std::enable_if<is_to_hex<Type>()>::type toJsonKey(rapidjson::Writer<epee::byte_stream>& dest, const Type& pod)
128 {
129  const auto hex = epee::to_hex::array(pod);
130  dest.Key(hex.data(), hex.size());
131 }
132 
133 // POD to json value
134 template <class Type>
135 inline typename std::enable_if<is_to_hex<Type>()>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Type& pod)
136 {
137  const auto hex = epee::to_hex::array(pod);
138  dest.String(hex.data(), hex.size());
139 }
140 
141 template <class Type>
142 inline typename std::enable_if<is_to_hex<Type>()>::type fromJsonValue(const rapidjson::Value& val, Type& t)
143 {
144  static_assert(std::is_standard_layout<Type>(), "expected standard layout type");
145  json::read_hex(val, epee::as_mut_byte_span(t));
146 }
147 
148 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rapidjson::Value& src);
149 
150 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, boost::string_ref i);
151 inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::string& i)
152 {
153  toJsonValue(dest, boost::string_ref{i});
154 }
155 void fromJsonValue(const rapidjson::Value& val, std::string& str);
156 
157 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::vector<std::uint8_t>&);
158 void fromJsonValue(const rapidjson::Value& src, std::vector<std::uint8_t>& i);
159 
160 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i);
161 void fromJsonValue(const rapidjson::Value& val, bool& b);
162 
163 // integers overloads for toJsonValue are not needed for standard promotions
164 
165 void fromJsonValue(const rapidjson::Value& val, unsigned char& i);
166 
167 void fromJsonValue(const rapidjson::Value& val, signed char& i);
168 
169 void fromJsonValue(const rapidjson::Value& val, char& i);
170 
171 void fromJsonValue(const rapidjson::Value& val, unsigned short& i);
172 
173 void fromJsonValue(const rapidjson::Value& val, short& i);
174 
175 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned i);
176 void fromJsonValue(const rapidjson::Value& val, unsigned& i);
177 
178 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const int);
179 void fromJsonValue(const rapidjson::Value& val, int& i);
180 
181 
182 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long long i);
183 void fromJsonValue(const rapidjson::Value& val, unsigned long long& i);
184 
185 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long long i);
186 void fromJsonValue(const rapidjson::Value& val, long long& i);
187 
188 inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long i) {
189  toJsonValue(dest, static_cast<unsigned long long>(i));
190 }
191 void fromJsonValue(const rapidjson::Value& val, unsigned long& i);
192 
193 inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long i) {
194  toJsonValue(dest, static_cast<long long>(i));
195 }
196 void fromJsonValue(const rapidjson::Value& val, long& i);
197 
198 // end integers
199 
200 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::transaction& tx);
201 void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx);
202 
203 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block& b);
204 void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b);
205 
206 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_v& txin);
207 void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_v& txin);
208 
209 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_gen& txin);
210 void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_gen& txin);
211 
212 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_script& txin);
213 void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_script& txin);
214 
215 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_scripthash& txin);
216 void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_scripthash& txin);
217 
218 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_key& txin);
219 void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin);
220 
221 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_target_v& txout);
222 void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_target_v& txout);
223 
224 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_script& txout);
225 void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txout);
226 
227 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_scripthash& txout);
228 void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash& txout);
229 
230 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_key& txout);
231 void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout);
232 
233 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout);
234 void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout);
235 
236 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::connection_info& info);
237 void fromJsonValue(const rapidjson::Value& val, cryptonote::connection_info& info);
238 
239 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_blob_entry& tx);
240 void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_blob_entry& tx);
241 
242 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block_complete_entry& blk);
243 void fromJsonValue(const rapidjson::Value& val, cryptonote::block_complete_entry& blk);
244 
245 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::block_with_transactions& blk);
246 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::block_with_transactions& blk);
247 
248 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::transaction_info& tx_info);
249 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::transaction_info& tx_info);
250 
251 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_and_amount_index& out);
252 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_and_amount_index& out);
253 
254 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::amount_with_random_outputs& out);
255 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::amount_with_random_outputs& out);
256 
257 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::peer& peer);
258 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::peer& peer);
259 
260 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::tx_in_pool& tx);
261 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::tx_in_pool& tx);
262 
263 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::hard_fork_info& info);
264 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::hard_fork_info& info);
265 
266 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_count& out);
267 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_count& out);
268 
269 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_and_index& out);
270 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_and_index& out);
271 
272 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_mask_unlocked& out);
273 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_mask_unlocked& out);
274 
275 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::error& err);
276 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error);
277 
278 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
279 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResponse& response);
280 
281 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& i);
282 void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
283 
284 void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key);
285 
286 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple);
287 void fromJsonValue(const rapidjson::Value& val, rct::ecdhTuple& tuple);
288 
289 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rangeSig& sig);
290 void fromJsonValue(const rapidjson::Value& val, rct::rangeSig& sig);
291 
292 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::Bulletproof& p);
293 void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p);
294 
295 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig);
296 void fromJsonValue(const rapidjson::Value& val, rct::boroSig& sig);
297 
298 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::mgSig& sig);
299 void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig);
300 
301 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info);
302 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info);
303 
304 void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist);
305 void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_distribution& dist);
306 
307 template <typename Map>
308 typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map);
309 
310 template <typename Map>
311 typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type fromJsonValue(const rapidjson::Value& val, Map& map);
312 
313 template <typename Vec>
314 typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec);
315 
316 template <typename Vec>
317 typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec);
318 
319 
320 // ideally would like to have the below functions in the .cpp file, but
321 // unfortunately because of how templates work they have to be here.
322 
323 template <typename Map>
324 inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map)
325 {
326  using key_type = typename Map::key_type;
327  static_assert(std::is_same<std::string, key_type>() || is_to_hex<key_type>(), "invalid map key type");
328 
329  dest.StartObject();
330  for (const auto& i : map)
331  {
332  toJsonKey(dest, i.first);
333  toJsonValue(dest, i.second);
334  }
335  dest.EndObject();
336 }
337 
338 template <typename Map>
339 inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type fromJsonValue(const rapidjson::Value& val, Map& map)
340 {
341  if (!val.IsObject())
342  {
343  throw WRONG_TYPE("json object");
344  }
345 
346  auto itr = val.MemberBegin();
347 
348  map.clear();
349  while (itr != val.MemberEnd())
350  {
351  typename Map::key_type k;
352  typename Map::mapped_type m;
353  fromJsonValue(itr->name, k);
354  fromJsonValue(itr->value, m);
355  map.emplace(k, m);
356  ++itr;
357  }
358 }
359 
360 template <typename Vec>
361 inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec)
362 {
363  using value_type = typename Vec::value_type;
364  static_assert(!std::is_same<value_type, char>::value, "encoding an array of chars is faster as hex");
365  static_assert(!std::is_same<value_type, unsigned char>::value, "encoding an array of unsigned char is faster as hex");
366 
367  dest.StartArray();
368  for (const auto& t : vec)
369  toJsonValue(dest, t);
370  dest.EndArray();
371 }
372 
373 namespace traits
374 {
375  template<typename T>
376  void reserve(const T&, std::size_t)
377  {}
378 
379  template<typename T>
380  void reserve(std::vector<T>& vec, const std::size_t count)
381  {
382  vec.reserve(count);
383  }
384 }
385 
386 template <typename Vec>
387 inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec)
388 {
389  using value_type = typename Vec::value_type;
390  static_assert(!std::is_same<value_type, char>::value, "encoding a vector of chars is faster as hex");
391  static_assert(!std::is_same<value_type, unsigned char>::value, "encoding a vector of unsigned char is faster as hex");
392 
393  if (!val.IsArray())
394  {
395  throw WRONG_TYPE("json array");
396  }
397 
398  vec.clear();
399  traits::reserve(vec, val.Size());
400  for (rapidjson::SizeType i=0; i < val.Size(); i++)
401  {
402  vec.emplace_back();
403  fromJsonValue(val[i], vec.back());
404  }
405 }
406 
407 } // namespace json
408 
409 } // namespace cryptonote
Definition: cryptonote_basic.h:194
const uint32_t T[512]
Definition: groestl_tables.h:36
int b
Definition: base.py:1
void reserve(const T &, std::size_t)
Definition: json_object.h:376
constexpr bool is_to_hex()
Definition: json_object.h:118
void read_hex(const rapidjson::Value &val, epee::span< std::uint8_t > dest)
Definition: json_object.cpp:118
void fromJsonValue(const rapidjson::Value &val, std::string &str)
Definition: json_object.cpp:141
std::enable_if< is_to_hex< Type >)>::type toJsonKey(rapidjson::Writer< epee::byte_stream > &dest, const Type &pod)
Definition: json_object.h:127
void toJsonValue(rapidjson::Writer< epee::byte_stream > &dest, const rapidjson::Value &src)
Definition: json_object.cpp:131
Holds cryptonote related classes and helpers.
Definition: blockchain_db.cpp:45
boost::variant< txout_to_script, txout_to_scripthash, txout_to_key > txout_target_v
Definition: cryptonote_basic.h:139
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key > txin_v
Definition: cryptonote_basic.h:137
std::string hex(difficulty_type v)
Definition: difficulty.cpp:242
mdb_size_t count(MDB_cursor *cur)
Definition: value_stream.cpp:39
error
Tracks LMDB error codes.
Definition: error.h:45
CXA_THROW_INFO_T void(* dest)(void *))
Definition: stack_trace.cpp:90
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:90
Definition: cryptonote_protocol_defs.h:133
Definition: cryptonote_basic.h:464
Definition: cryptonote_protocol_defs.h:48
Definition: json_object.h:102
BAD_INPUT()
Definition: json_object.h:103
Definition: json_object.h:71
std::string m
Definition: json_object.h:74
const char * what() const
Definition: json_object.h:79
virtual ~JSON_ERROR()
Definition: json_object.h:77
JSON_ERROR()
Definition: json_object.h:73
Definition: json_object.h:86
MISSING_KEY(const char *key)
Definition: json_object.h:87
Definition: json_object.h:110
PARSE_FAIL()
Definition: json_object.h:111
Definition: json_object.h:94
WRONG_TYPE(const char *type)
Definition: json_object.h:95
Definition: core_rpc_server_commands_defs.h:1159
Definition: message_data_structs.h:161
Definition: message_data_structs.h:176
Definition: message_data_structs.h:72
Definition: message_data_structs.h:47
Definition: message_data_structs.h:144
Definition: message_data_structs.h:131
Definition: message_data_structs.h:118
Definition: message_data_structs.h:110
Definition: message_data_structs.h:206
Definition: message_data_structs.h:64
Definition: message_data_structs.h:124
Definition: message_data_structs.h:78
Definition: message_data_structs.h:57
Definition: message_data_structs.h:89
Definition: cryptonote_protocol_defs.h:122
Definition: core_rpc_server_commands_defs.h:1344
Definition: cryptonote_basic.h:143
Definition: cryptonote_basic.h:87
Definition: cryptonote_basic.h:124
Definition: cryptonote_basic.h:96
Definition: cryptonote_basic.h:109
Definition: cryptonote_basic.h:77
Definition: cryptonote_basic.h:61
Definition: cryptonote_basic.h:72
Definition: rctTypes.h:205
Definition: rctTypes.h:147
Definition: rctTypes.h:97
Definition: rctTypes.h:132
Definition: rctTypes.h:160
Definition: rctTypes.h:194
Definition: rctTypes.h:536
rapidjson::Document json
Definition: transport.cpp:49