diff options
Diffstat (limited to 'src/serialization')
-rw-r--r-- | src/serialization/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/serialization/json_object.cpp | 73 | ||||
-rw-r--r-- | src/serialization/json_object.h | 37 |
3 files changed, 90 insertions, 21 deletions
diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index a2e7c353e..34e274b6c 100644 --- a/src/serialization/CMakeLists.txt +++ b/src/serialization/CMakeLists.txt @@ -42,6 +42,7 @@ monero_add_library(serialization ${serialization_private_headers}) target_link_libraries(serialization LINK_PRIVATE + cryptonote_basic cryptonote_core cryptonote_protocol epee diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 5c042aa7b..7c48cf6c3 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -33,6 +33,8 @@ #include <limits> #include <type_traits> +#include "cryptonote_basic/cryptonote_basic_impl.h" + // drop macro from windows.h #ifdef GetObject #undef GetObject @@ -146,6 +148,26 @@ void fromJsonValue(const rapidjson::Value& val, std::string& str) str = val.GetString(); } +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::vector<std::uint8_t>& src) +{ + const std::string hex = epee::to_hex::string(epee::to_span(src)); + dest.String(hex.data(), hex.size()); +} + +void fromJsonValue(const rapidjson::Value& val, std::vector<std::uint8_t>& dest) +{ + if (!val.IsString()) + { + throw WRONG_TYPE("string"); + } + + dest.resize(val.GetStringLength() / 2); + if ((val.GetStringLength() % 2) != 0 || !epee::from_hex::to_buffer(epee::to_mut_span(dest), {val.GetString(), val.GetStringLength()})) + { + throw BAD_INPUT(); + } +} + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i) { dest.Bool(i); @@ -246,7 +268,10 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t INSERT_INTO_JSON_OBJECT(dest, inputs, tx.vin); INSERT_INTO_JSON_OBJECT(dest, outputs, tx.vout); INSERT_INTO_JSON_OBJECT(dest, extra, tx.extra); - INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures); + if (!tx.pruned) + { + INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures); + } INSERT_INTO_JSON_OBJECT(dest, ringct, tx.rct_signatures); dest.EndObject(); @@ -265,8 +290,17 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx) GET_FROM_JSON_OBJECT(val, tx.vin, inputs); GET_FROM_JSON_OBJECT(val, tx.vout, outputs); GET_FROM_JSON_OBJECT(val, tx.extra, extra); - GET_FROM_JSON_OBJECT(val, tx.signatures, signatures); GET_FROM_JSON_OBJECT(val, tx.rct_signatures, ringct); + + const auto& sigs = val.FindMember("signatures"); + if (sigs != val.MemberEnd()) + { + fromJsonValue(sigs->value, tx.signatures); + } + + const auto& rsig = tx.rct_signatures; + if (!cryptonote::is_coinbase(tx) && rsig.p.bulletproofs.empty() && rsig.p.rangeSigs.empty() && rsig.p.MGs.empty() && rsig.get_pseudo_outs().empty() && sigs == val.MemberEnd()) + tx.pruned = true; } void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block& b) @@ -1062,6 +1096,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); // prunable + if (!sig.p.bulletproofs.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()) { dest.Key("prunable"); dest.StartObject(); @@ -1086,35 +1121,39 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) throw WRONG_TYPE("json object"); } - std::vector<rct::key> commitments; - GET_FROM_JSON_OBJECT(val, sig.type, type); GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); - GET_FROM_JSON_OBJECT(val, commitments, commitments); + GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); // prunable + const auto prunable = val.FindMember("prunable"); + if (prunable != val.MemberEnd()) { - OBJECT_HAS_MEMBER_OR_THROW(val, "prunable"); - const auto& prunable = val["prunable"]; - - rct::keyV pseudo_outs; + rct::keyV pseudo_outs = std::move(sig.get_pseudo_outs()); - GET_FROM_JSON_OBJECT(prunable, sig.p.rangeSigs, range_proofs); - GET_FROM_JSON_OBJECT(prunable, sig.p.bulletproofs, bulletproofs); - GET_FROM_JSON_OBJECT(prunable, sig.p.MGs, mlsags); - GET_FROM_JSON_OBJECT(prunable, pseudo_outs, pseudo_outs); + GET_FROM_JSON_OBJECT(prunable->value, sig.p.rangeSigs, range_proofs); + GET_FROM_JSON_OBJECT(prunable->value, sig.p.bulletproofs, bulletproofs); + GET_FROM_JSON_OBJECT(prunable->value, sig.p.MGs, mlsags); + GET_FROM_JSON_OBJECT(prunable->value, pseudo_outs, pseudo_outs); sig.get_pseudo_outs() = std::move(pseudo_outs); } - - sig.outPk.reserve(commitments.size()); - for (rct::key const& commitment : commitments) + else { - sig.outPk.push_back({{}, commitment}); + sig.p.rangeSigs.clear(); + sig.p.bulletproofs.clear(); + sig.p.MGs.clear(); + sig.get_pseudo_outs().clear(); } } +void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key) +{ + key.dest = {}; + fromJsonValue(val, key.mask); +} + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple) { dest.StartObject(); diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index 2a9b63b08..de14c8911 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -32,6 +32,7 @@ #include <cstring> #include <rapidjson/document.h> #include <rapidjson/writer.h> +#include <vector> #include "byte_stream.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -153,6 +154,9 @@ inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::s } void fromJsonValue(const rapidjson::Value& val, std::string& str); +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::vector<std::uint8_t>&); +void fromJsonValue(const rapidjson::Value& src, std::vector<std::uint8_t>& i); + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i); void fromJsonValue(const rapidjson::Value& val, bool& b); @@ -277,6 +281,8 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResp void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& i); void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig); +void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key); + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple); void fromJsonValue(const rapidjson::Value& val, rct::ecdhTuple& tuple); @@ -339,6 +345,7 @@ inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type from auto itr = val.MemberBegin(); + map.clear(); while (itr != val.MemberEnd()) { typename Map::key_type k; @@ -353,25 +360,47 @@ inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type from template <typename Vec> inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec) { + using value_type = typename Vec::value_type; + static_assert(!std::is_same<value_type, char>::value, "encoding an array of chars is faster as hex"); + static_assert(!std::is_same<value_type, unsigned char>::value, "encoding an array of unsigned char is faster as hex"); + dest.StartArray(); for (const auto& t : vec) toJsonValue(dest, t); - dest.EndArray(vec.size()); + dest.EndArray(); +} + +namespace traits +{ + template<typename T> + void reserve(const T&, std::size_t) + {} + + template<typename T> + void reserve(std::vector<T>& vec, const std::size_t count) + { + vec.reserve(count); + } } template <typename Vec> inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec) { + using value_type = typename Vec::value_type; + static_assert(!std::is_same<value_type, char>::value, "encoding a vector of chars is faster as hex"); + static_assert(!std::is_same<value_type, unsigned char>::value, "encoding a vector of unsigned char is faster as hex"); + if (!val.IsArray()) { throw WRONG_TYPE("json array"); } + vec.clear(); + traits::reserve(vec, val.Size()); for (rapidjson::SizeType i=0; i < val.Size(); i++) { - typename Vec::value_type v; - fromJsonValue(val[i], v); - vec.push_back(v); + vec.emplace_back(); + fromJsonValue(val[i], vec.back()); } } |