diff --git a/CMakeLists.txt b/CMakeLists.txt index 375842f..1f2c67e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,9 +65,16 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32) set_property(TARGET unbound PROPERTY IMPORTED_LOCATION ${MONERO_BUILD_DIR}/external/unbound/libunbound.a) endif() + + # include boost headers include_directories(${Boost_INCLUDE_DIRS}) + +# include monero +include_directories(${MONERO_SOURCE_DIR}/build) + include_directories("ext/mstch/include") +include_directories("ext/mstch/include/src") include_directories("ext/crow") # add ext/ subfolder diff --git a/main.cpp b/main.cpp index 4729298..2a7e544 100644 --- a/main.cpp +++ b/main.cpp @@ -336,9 +336,14 @@ main(int ac, const char* av[]) return crow::response(xmrblocks.show_block_hex(block_height, true)); }); +// CROW_ROUTE(app, "/ringmemberstxhex/") +// ([&](string tx_hash) { +// return crow::response(xmrblocks.show_ringmemberstx_hex(remove_bad_chars(tx_hash))); +// }); + CROW_ROUTE(app, "/ringmemberstxhex/") ([&](string tx_hash) { - return crow::response(xmrblocks.show_ringmemberstx_hex(remove_bad_chars(tx_hash))); + return myxmr::jsonresponse {xmrblocks.show_ringmemberstx_jsonhex(remove_bad_chars(tx_hash))}; }); } diff --git a/src/page.h b/src/page.h index e0680ef..b3aa228 100644 --- a/src/page.h +++ b/src/page.h @@ -22,15 +22,20 @@ #include "../ext/crow/crow.h" +#include "../ext/json.hpp" + #include "../ext/vpetrigocaches/cache.hpp" #include "../ext/vpetrigocaches/lru_cache_policy.hpp" #include "../ext/vpetrigocaches/fifo_cache_policy.hpp" +#include "../ext/mstch/src/visitor/render_node.hpp" + + #include #include #include #include -#include + #define TMPL_DIR "./templates" @@ -190,8 +195,6 @@ using namespace std; using epee::string_tools::pod_to_hex; using epee::string_tools::hex_to_pod; - - /** * @brief The tx_details struct * @@ -1842,7 +1845,200 @@ show_ringmemberstx_hex(string const& tx_hash_str) ::buff_to_hex_nodelimer(oss.str()); } +/** + * @brief Get ring member tx data + * + * Used for generating json file of txs used in unit testing. + * Thanks to json output from this function, we can mock + * a number of blockchain quries about key images + * + * @param tx_hash_str + * @return + */ +json +show_ringmemberstx_jsonhex(string const& tx_hash_str) +{ + transaction tx; + crypto::hash tx_hash; + if (!get_tx(tx_hash_str, tx, tx_hash)) + return string {"Cant get tx: "} + tx_hash_str; + + vector input_key_imgs = xmreg::get_key_images(tx); + + json tx_json; + + string tx_hex; + + try + { + tx_hex = tx_to_hex(tx); + } + catch (std::exception const& e) + { + cerr << e.what() << endl; + return json {"error", "Failed to obtain hex of tx"}; + } + + tx_json["hash"] = tx_hash_str; + tx_json["hex"] = tx_hex; + tx_json["nettype"] = static_cast(nettype); + tx_json["_comment"] = "Just a placeholder for some comment if needed later"; + + uint64_t tx_blk_height {0}; + + try + { + tx_blk_height = core_storage->get_db().get_tx_block_height(tx_hash); + } + catch (exception& e) + { + cerr << "Cant get block height: " << tx_hash + << e.what() << endl; + + return json {"error", "Cant get block height"}; + } + + // get block cointaining this tx + block blk; + + if ( !mcore->get_block_by_height(tx_blk_height, blk)) + { + cerr << "Cant get block: " << tx_blk_height << endl; + return json {"error", "Cant get block"}; + } + + block_complete_entry complete_block_data; + + if (!mcore->get_block_complete_entry(blk, complete_block_data)) + { + cerr << "Failed to obtain complete block data " << endl; + return json {"error", "Failed to obtain complete block data "}; + } + + std::string complete_block_data_str; + + if(!epee::serialization::store_t_to_binary( + complete_block_data, complete_block_data_str)) + { + cerr << "Failed to serialize complete_block_data\n"; + return json {"error", "Failed to obtain complete block data"}; + } + + tx_json["block"] = epee::string_tools + ::buff_to_hex_nodelimer(complete_block_data_str); + + + tx_json["inputs"] = json::array(); + + + // key: constracted from concatenation of in_key.amount and absolute_offsets, + // value: vector of string where string is transaction hash + output index + tx_hex + // will have to cut this string when de-seraializing this data + // later in the unit tests + // transaction hash and output index represent tx_out_index + std::map> all_mixin_txs; + + for (txin_to_key const& in_key: input_key_imgs) + { + // get absolute offsets of mixins + std::vector absolute_offsets + = cryptonote::relative_output_offsets_to_absolute( + in_key.key_offsets); + + //tx_out_index is pair:: + vector indices; + std::vector mixin_outputs; + + // get tx hashes and indices in the txs for the + // given outputs of mixins + // this cant THROW DB_EXCEPTION + try + { + // get tx of the real output + core_storage->get_db().get_output_tx_and_index( + in_key.amount, absolute_offsets, indices); + + // get mining ouput info + core_storage->get_db().get_output_key( + epee::span(&in_key.amount, 1), + absolute_offsets, + mixin_outputs); + } + catch (exception const& e) + { + + string out_msg = fmt::format( + "Cant get ring member tx_out_index for tx {:s}", tx_hash_str + ); + + cerr << out_msg << endl; + + return json {"error", out_msg}; + } + + + tx_json["inputs"].push_back(json {{"key_image", pod_to_hex(in_key.k_image)}, + {"amount", in_key.amount}, + {"absolute_offsets", absolute_offsets}, + {"ring_members", json::array()}}); + + json& ring_members = tx_json["inputs"].back()["ring_members"]; + + + if (indices.size() != mixin_outputs.size()) + { + cerr << "indices.size() != mixin_outputs.size()\n"; + return json {"error", "indices.size() != mixin_outputs.size()"}; + } + + // serialize each mixin tx + //for (auto const& txi : indices) + for (size_t i = 0; i < indices.size(); ++i) + { + + tx_out_index const& txi = indices[i]; + output_data_t const& mo = mixin_outputs[i]; + + auto const& mixin_tx_hash = txi.first; + auto const& output_index_in_tx = txi.second; + + transaction mixin_tx; + + if (!mcore->get_tx(mixin_tx_hash, mixin_tx)) + { + throw std::runtime_error("Cant get tx: " + + pod_to_hex(mixin_tx_hash)); + } + + // serialize tx + string tx_hex = epee::string_tools::buff_to_hex_nodelimer( + t_serializable_object_to_blob(mixin_tx)); + + ring_members.push_back( + json { + {"ouput_pk", pod_to_hex(mo.pubkey)}, + {"tx_hash", pod_to_hex(mixin_tx_hash)}, + {"output_index_in_tx", txi.second}, + {"tx_hex", tx_hex}, + }); + + } + + } // for (txin_to_key const& in_key: input_key_imgs) + + + // archive all_mixin_outputs vector + std::ostringstream oss; + boost::archive::portable_binary_oarchive archive(oss); + archive << all_mixin_txs; + + // return as all_mixin_outputs vector hex + //return epee::string_tools + // ::buff_to_hex_nodelimer(oss.str()); + + return tx_json; +} string show_my_outputs(string tx_hash_str, @@ -4642,7 +4838,7 @@ json_block(string block_no_or_hash) {"data" , json {}} }; - json& j_data = j_response["data"]; + nlohmann::json& j_data = j_response["data"]; uint64_t current_blockchain_height = core_storage->get_current_blockchain_height();