Monero
Loading...
Searching...
No Matches
json_object.h
Go to the documentation of this file.
1// Copyright (c) 2016-2022, 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"
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
64namespace cryptonote
65{
66
67namespace json
68{
69
70struct JSON_ERROR : public std::exception
71{
72 protected:
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
85struct 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
93struct 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
101struct BAD_INPUT : public JSON_ERROR
102{
104 {
105 m = "An item failed to convert from json object to native object";
106 }
107};
108
109struct PARSE_FAIL : public JSON_ERROR
110{
112 {
113 m = "Failed to parse the json request";
114 }
115};
116
117template<typename Type>
118inline constexpr bool is_to_hex()
119{
120 return std::is_pod<Type>() && !std::is_integral<Type>();
121}
122
123void read_hex(const rapidjson::Value& val, epee::span<std::uint8_t> dest);
124
125// POD to json key
126template <class Type>
127inline 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
134template <class Type>
135inline 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
141template <class Type>
142inline 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
148void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rapidjson::Value& src);
149
150void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, boost::string_ref i);
151inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::string& i)
152{
153 toJsonValue(dest, boost::string_ref{i});
154}
155void fromJsonValue(const rapidjson::Value& val, std::string& str);
156
157void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::vector<std::uint8_t>&);
158void fromJsonValue(const rapidjson::Value& src, std::vector<std::uint8_t>& i);
159
160void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i);
161void fromJsonValue(const rapidjson::Value& val, bool& b);
162
163// integers overloads for toJsonValue are not needed for standard promotions
164
165void fromJsonValue(const rapidjson::Value& val, unsigned char& i);
166
167void fromJsonValue(const rapidjson::Value& val, signed char& i);
168
169void fromJsonValue(const rapidjson::Value& val, char& i);
170
171void fromJsonValue(const rapidjson::Value& val, unsigned short& i);
172
173void fromJsonValue(const rapidjson::Value& val, short& i);
174
175void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned i);
176void fromJsonValue(const rapidjson::Value& val, unsigned& i);
177
178void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const int);
179void fromJsonValue(const rapidjson::Value& val, int& i);
180
181
182void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long long i);
183void fromJsonValue(const rapidjson::Value& val, unsigned long long& i);
184
185void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long long i);
186void fromJsonValue(const rapidjson::Value& val, long long& i);
187
188inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long i) {
189 toJsonValue(dest, static_cast<unsigned long long>(i));
190}
191void fromJsonValue(const rapidjson::Value& val, unsigned long& i);
192
193inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long i) {
194 toJsonValue(dest, static_cast<long long>(i));
195}
196void fromJsonValue(const rapidjson::Value& val, long& i);
197
198// end integers
199
200void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::transaction& tx);
201void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx);
202
203void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block& b);
204void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b);
205
206void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_v& txin);
207void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_v& txin);
208
209void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_gen& txin);
210void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_gen& txin);
211
212void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_script& txin);
213void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_script& txin);
214
215void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_scripthash& txin);
216void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_scripthash& txin);
217
218void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_key& txin);
219void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin);
220
221void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_target_v& txout);
222void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_target_v& txout);
223
224void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_script& txout);
225void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txout);
226
227void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_scripthash& txout);
228void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash& txout);
229
230void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_key& txout);
231void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout);
232
233void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_tagged_key& txout);
234void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_tagged_key& txout);
235
236void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout);
237void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout);
238
239void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::connection_info& info);
240void fromJsonValue(const rapidjson::Value& val, cryptonote::connection_info& info);
241
242void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_blob_entry& tx);
243void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_blob_entry& tx);
244
245void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block_complete_entry& blk);
246void fromJsonValue(const rapidjson::Value& val, cryptonote::block_complete_entry& blk);
247
248void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::block_with_transactions& blk);
249void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::block_with_transactions& blk);
250
251void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::transaction_info& tx_info);
252void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::transaction_info& tx_info);
253
254void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_and_amount_index& out);
255void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_and_amount_index& out);
256
257void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::amount_with_random_outputs& out);
258void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::amount_with_random_outputs& out);
259
260void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::peer& peer);
261void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::peer& peer);
262
263void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::tx_in_pool& tx);
264void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::tx_in_pool& tx);
265
266void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::hard_fork_info& info);
267void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::hard_fork_info& info);
268
269void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_count& out);
270void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_count& out);
271
272void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_and_index& out);
273void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_and_index& out);
274
275void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_mask_unlocked& out);
276void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_mask_unlocked& out);
277
278void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::error& err);
279void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error);
280
281void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
282void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResponse& response);
283
284void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, bool prune);
285void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
286
287void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key);
288
289void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple);
290void fromJsonValue(const rapidjson::Value& val, rct::ecdhTuple& tuple);
291
292void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rangeSig& sig);
293void fromJsonValue(const rapidjson::Value& val, rct::rangeSig& sig);
294
295void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::Bulletproof& p);
296void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p);
297
298void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::BulletproofPlus& p);
299void fromJsonValue(const rapidjson::Value& val, rct::BulletproofPlus& p);
300
301void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig);
302void fromJsonValue(const rapidjson::Value& val, rct::boroSig& sig);
303
304void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::mgSig& sig);
305void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig);
306
307void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::clsag& sig);
308void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig);
309
310void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info);
311void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info);
312
313void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist);
314void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_distribution& dist);
315
316void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_block_template_backlog_entry& entry);
317void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_block_template_backlog_entry& entry);
318
319template <typename Map>
320typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map);
321
322template <typename Map>
323typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type fromJsonValue(const rapidjson::Value& val, Map& map);
324
325template <typename Vec>
326typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec);
327
328template <typename Vec>
329typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec);
330
331
332// ideally would like to have the below functions in the .cpp file, but
333// unfortunately because of how templates work they have to be here.
334
335template <typename Map>
336inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map)
337{
338 using key_type = typename Map::key_type;
339 static_assert(std::is_same<std::string, key_type>() || is_to_hex<key_type>(), "invalid map key type");
340
341 dest.StartObject();
342 for (const auto& i : map)
343 {
344 toJsonKey(dest, i.first);
345 toJsonValue(dest, i.second);
346 }
347 dest.EndObject();
348}
349
350template <typename Map>
351inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type fromJsonValue(const rapidjson::Value& val, Map& map)
352{
353 if (!val.IsObject())
354 {
355 throw WRONG_TYPE("json object");
356 }
357
358 auto itr = val.MemberBegin();
359
360 map.clear();
361 while (itr != val.MemberEnd())
362 {
363 typename Map::key_type k;
364 typename Map::mapped_type m;
365 fromJsonValue(itr->name, k);
366 fromJsonValue(itr->value, m);
367 map.emplace(k, m);
368 ++itr;
369 }
370}
371
372template <typename Vec>
373inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec)
374{
375 using value_type = typename Vec::value_type;
376 static_assert(!std::is_same<value_type, char>::value, "encoding an array of chars is faster as hex");
377 static_assert(!std::is_same<value_type, unsigned char>::value, "encoding an array of unsigned char is faster as hex");
378
379 dest.StartArray();
380 for (auto t : vec)
381 toJsonValue(dest, t);
382 dest.EndArray();
383}
384
385namespace traits
386{
387 template<typename T>
388 void reserve(const T&, std::size_t)
389 {}
390
391 template<typename T>
392 void reserve(std::vector<T>& vec, const std::size_t count)
393 {
394 vec.reserve(count);
395 }
396}
397
398template <typename Vec>
399inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec)
400{
401 using value_type = typename Vec::value_type;
402 static_assert(!std::is_same<value_type, char>::value, "encoding a vector of chars is faster as hex");
403 static_assert(!std::is_same<value_type, unsigned char>::value, "encoding a vector of unsigned char is faster as hex");
404
405 if (!val.IsArray())
406 {
407 throw WRONG_TYPE("json array");
408 }
409
410 vec.clear();
411 traits::reserve(vec, val.Size());
412 for (rapidjson::SizeType i=0; i < val.Size(); i++)
413 {
414 vec.emplace_back();
415 fromJsonValue(val[i], vec.back());
416 }
417}
418
419} // namespace json
420
421} // namespace cryptonote
cryptonote::block b
Definition block.cpp:40
static void prune(MDB_env *env0, MDB_env *env1)
Definition blockchain_prune.cpp:249
Definition cryptonote_basic.h:205
Non-owning sequence of data. Does not deep copy.
Definition span.h:55
const char * key
Definition hmac_keccak.cpp:40
static MDB_envinfo info
Definition mdb_load.c:37
Definition json_object.h:386
void reserve(const T &, std::size_t)
Definition json_object.h:388
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:119
void fromJsonValue(const rapidjson::Value &val, std::string &str)
Definition json_object.cpp:142
void toJsonValue(rapidjson::Writer< epee::byte_stream > &dest, const rapidjson::Value &src)
Definition json_object.cpp:132
std::enable_if< is_to_hex< Type >()>::type toJsonKey(rapidjson::Writer< epee::byte_stream > &dest, const Type &pod)
Definition json_object.h:127
Holds cryptonote related classes and helpers.
Definition blockchain_db.cpp:45
boost::variant< txout_to_script, txout_to_scripthash, txout_to_key, txout_to_tagged_key > txout_target_v
Definition cryptonote_basic.h:154
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key > txin_v
Definition cryptonote_basic.h:152
std::string hex(difficulty_type v)
Definition difficulty.cpp:242
span< std::uint8_t > as_mut_byte_span(T &src) noexcept
Definition span.h:172
const char *const str
Definition portlistingparse.c:23
Type
Type of JSON value.
Definition rapidjson.h:623
CXA_THROW_INFO_T void(* dest)(void *))
Definition stack_trace.cpp:91
Definition cryptonote_protocol_defs.h:133
Definition cryptonote_basic.h:475
Definition cryptonote_protocol_defs.h:48
BAD_INPUT()
Definition json_object.h:103
const char * what() const
Definition json_object.h:79
std::string m
Definition json_object.h:74
virtual ~JSON_ERROR()
Definition json_object.h:77
JSON_ERROR()
Definition json_object.h:73
MISSING_KEY(const char *key)
Definition json_object.h:87
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:1338
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:207
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 cryptonote_tx_utils.h:113
Definition core_rpc_server_commands_defs.h:1523
Definition cryptonote_basic.h:158
Definition cryptonote_basic.h:102
Definition cryptonote_basic.h:139
Definition cryptonote_basic.h:111
Definition cryptonote_basic.h:124
Definition cryptonote_basic.h:79
Definition cryptonote_basic.h:62
Definition cryptonote_basic.h:73
Definition cryptonote_basic.h:87
static std::array< char, N *2 > array(const std::array< std::uint8_t, N > &src) noexcept
Definition hex.h:52
Definition rctTypes.h:250
Definition rctTypes.h:213
Definition rctTypes.h:155
Definition rctTypes.h:181
Definition rctTypes.h:97
Definition rctTypes.h:140
Definition rctTypes.h:168
Definition rctTypes.h:202
Definition rctTypes.h:613
cryptonote::transaction tx
Definition transaction.cpp:40
rapidjson::Document json
Definition transport.cpp:49
#define T(x)