From f896490c21997ed5d75aec47ac81b8fdcd5364be Mon Sep 17 00:00:00 2001 From: Guten Ye Date: Wed, 21 Nov 2018 15:13:17 +0800 Subject: [PATCH] Added decodeRctSimple --- src/serial_bridge_index.cpp | 71 +++++++++++++++++++++++++++++++++++++ src/serial_bridge_index.hpp | 1 + test/test_all.cpp | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/src/serial_bridge_index.cpp b/src/serial_bridge_index.cpp index cbc00ee..c340b98 100644 --- a/src/serial_bridge_index.cpp +++ b/src/serial_bridge_index.cpp @@ -616,6 +616,77 @@ string serial_bridge::decodeRct(const string &args_string) // return ret_json_from_root(root); } +// +string serial_bridge::decodeRctSimple(const string &args_string) +{ + boost::property_tree::ptree json_root; + if (!parsed_json_root(args_string, json_root)) { + // it will already have thrown an exception + return error_ret_json_from_message("Invalid JSON"); + } + rct::key sk; + if (!epee::string_tools::hex_to_pod(json_root.get("sk"), sk)) { + return error_ret_json_from_message("Invalid 'sk'"); + } + unsigned int i = stoul(json_root.get("i")); + // NOTE: this rv structure parsing could be factored but it presently does not implement a number of sub-components of rv, such as .pseudoOuts + auto rv_desc = json_root.get_child("rv"); + rct::rctSig rv = AUTO_VAL_INIT(rv); + unsigned int rv_type_int = stoul(rv_desc.get("type")); + // got to be a better way to do this + if (rv_type_int == rct::RCTTypeNull) { + rv.type = rct::RCTTypeNull; + } else if (rv_type_int == rct::RCTTypeSimple) { + rv.type = rct::RCTTypeSimple; + } else if (rv_type_int == rct::RCTTypeFull) { + rv.type = rct::RCTTypeFull; + } else if (rv_type_int == rct::RCTTypeBulletproof) { + rv.type = rct::RCTTypeBulletproof; + } else { + return error_ret_json_from_message("Invalid 'rv.type'"); + } + BOOST_FOREACH(boost::property_tree::ptree::value_type &ecdh_info_desc, rv_desc.get_child("ecdhInfo")) + { + assert(ecdh_info_desc.first.empty()); // array elements have no names + auto ecdh_info = rct::ecdhTuple{}; + if (!epee::string_tools::hex_to_pod(ecdh_info_desc.second.get("mask"), ecdh_info.mask)) { + return error_ret_json_from_message("Invalid rv.ecdhInfo[].mask"); + } + if (!epee::string_tools::hex_to_pod(ecdh_info_desc.second.get("amount"), ecdh_info.amount)) { + return error_ret_json_from_message("Invalid rv.ecdhInfo[].amount"); + } + rv.ecdhInfo.push_back(ecdh_info); + } + BOOST_FOREACH(boost::property_tree::ptree::value_type &outPk_desc, rv_desc.get_child("outPk")) + { + assert(outPk_desc.first.empty()); // array elements have no names + auto outPk = rct::ctkey{}; + if (!epee::string_tools::hex_to_pod(outPk_desc.second.get("mask"), outPk.mask)) { + return error_ret_json_from_message("Invalid rv.outPk[].mask"); + } + // FIXME: does dest need to be placed on the key? + rv.outPk.push_back(outPk); + } + // + rct::key mask; + rct::xmr_amount/*uint64_t*/ decoded_amount; + try { + decoded_amount = rct::decodeRctSimple( + rv, sk, i, mask, + hw::get_device("default") // presently this uses the default device but we could let a string be passed to switch the type + ); + } catch (std::exception const& e) { + return error_ret_json_from_message(e.what()); + } + stringstream decoded_amount_ss; + decoded_amount_ss << decoded_amount; + // + boost::property_tree::ptree root; + root.put(ret_json_key__decodeRct_mask(), epee::string_tools::pod_to_hex(mask)); + root.put(ret_json_key__decodeRct_amount(), decoded_amount_ss.str()); + // + return ret_json_from_root(root); +} string serial_bridge::generate_key_derivation(const string &args_string) { boost::property_tree::ptree json_root; diff --git a/src/serial_bridge_index.hpp b/src/serial_bridge_index.hpp index 711f14f..f63570f 100644 --- a/src/serial_bridge_index.hpp +++ b/src/serial_bridge_index.hpp @@ -70,6 +70,7 @@ namespace serial_bridge string derive_public_key(const string &args_string); string derive_subaddress_public_key(const string &args_string); string decodeRct(const string &args_string); + string decodeRctSimple(const string &args_string); } #endif /* serial_bridge_index_hpp */ diff --git a/test/test_all.cpp b/test/test_all.cpp index 31d3ce3..6ea7626 100644 --- a/test/test_all.cpp +++ b/test/test_all.cpp @@ -1162,6 +1162,68 @@ BOOST_AUTO_TEST_CASE(bridged__decodeRct) cout << "bridged__decodeRct: amount_string: " << amount_string << endl; BOOST_REQUIRE(amount_string == "4501"); // FIXME is this correct? } +// +BOOST_AUTO_TEST_CASE(bridged__decodeRctSimple) +{ + using namespace serial_bridge; + // + boost::property_tree::ptree root; + root.put("i", "0"); + root.put("sk", "a2259749f7aad692e000af4b7f383f4441ba4085bf70e518081365750db73b06"); + + boost::property_tree::ptree rv; + { + rv.put("type", "3"); + // + boost::property_tree::ptree ecdhInfo; + { + boost::property_tree::ptree ecdh_info; + ecdh_info.put("mask", "dc9a2e8a66a336f67bb1a150f6de4522f09c451a10f450d7ee096baa75660a05"); + ecdh_info.put("amount", "0c8f7514fd1d7c4f49795f33254739ce8e96275b17f50a03c877ed4b56896601"); + ecdhInfo.push_back(std::make_pair("", ecdh_info)); + } + { + boost::property_tree::ptree ecdh_info; + ecdh_info.put("mask", "f0d94c21aa892ad4e0d492f5fce4b8e99ff5e1ed687134b9419a2290e8701004"); + ecdh_info.put("amount", "dbaeca613d37b53ff0a22a1fb6e09150baa6f4f5f6e145ef78a78cc19624a702"); + ecdhInfo.push_back(std::make_pair("", ecdh_info)); + } + rv.add_child("ecdhInfo", ecdhInfo); + // + boost::property_tree::ptree outPk; + { + boost::property_tree::ptree an_outPk; + an_outPk.put("mask", "4dd9e7e2a2d8f31f065562923079399ec6c90d4b155d289208001994815bd01f"); + outPk.push_back(std::make_pair("", an_outPk)); + } + { + boost::property_tree::ptree an_outPk; + an_outPk.put("mask", "c23cdb07e56bcb6a9ad087122b7079f2c34e217bcbddd16ca6031ab8828f7a84"); + outPk.push_back(std::make_pair("", an_outPk)); + } + rv.add_child("outPk", outPk); + } + root.add_child("rv", rv); + // + auto ret_string = serial_bridge::decodeRct(args_string_from_root(root)); + stringstream ret_stream; + ret_stream << ret_string; + boost::property_tree::ptree ret_tree; + boost::property_tree::read_json(ret_stream, ret_tree); + optional err_string = ret_tree.get_optional(ret_json_key__any__err_msg()); + if (err_string != none) { + BOOST_REQUIRE_MESSAGE(false, *err_string); + } + string mask_string = ret_tree.get(ret_json_key__decodeRct_mask()); + BOOST_REQUIRE(mask_string.size() > 0); + cout << "bridged__decodeRctSimple: mask_string: " << mask_string << endl; + BOOST_REQUIRE(mask_string == "51bdfc13c6757758148dd493a77e94073a062622a056a915a457abe6ca6c050b"); + string amount_string = ret_tree.get(ret_json_key__decodeRct_amount()); + BOOST_REQUIRE(amount_string.size() > 0); + cout << "bridged__decodeRctSimple: amount_string: " << amount_string << endl; + BOOST_REQUIRE(amount_string == "10000000000"); +} + // // // NOTE: output 0's rct field is actually borrowed from output 1 since it got deleted (and the stagenet account which produced this data has since been swept).