diff --git a/CMakeLists.txt b/CMakeLists.txt index 01d9242..f9af47a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,6 +297,7 @@ target_link_libraries(scratchpad set( LIBRARY_SRC_FILES src/wallet/MoneroWallet.cpp + src/utils/MoneroUtils.cpp ) add_library(monero-cpp SHARED ${LIBRARY_SRC_FILES}) diff --git a/src/utils/MoneroUtils.cpp b/src/utils/MoneroUtils.cpp new file mode 100644 index 0000000..9fd1c79 --- /dev/null +++ b/src/utils/MoneroUtils.cpp @@ -0,0 +1,75 @@ +#include "MoneroUtils.h" +#include "rpc/core_rpc_server_commands_defs.h" +#include "storages/portable_storage_template_helper.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include +#include + +using namespace std; +using namespace boost; +using namespace cryptonote; +using namespace MoneroUtils; + +void MoneroUtils::json_to_binary(const std::string &buff_json, std::string &buff_bin) { + epee::serialization::portable_storage ps; + ps.load_from_json(buff_json); + ps.store_to_binary(buff_bin); +} + +void MoneroUtils::binary_to_json(const std::string &buff_bin, std::string &buff_json) { + epee::serialization::portable_storage ps; + ps.load_from_binary(buff_bin); + ps.dump_as_json(buff_json); +} + +void MoneroUtils::binary_blocks_to_json(const std::string &buff_bin, std::string &buff_json) { + + // load binary rpc response to struct + cryptonote::COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::response resp_struct; + epee::serialization::load_t_from_binary(resp_struct, buff_bin); + + // build property tree from deserialized blocks and transactions + boost::property_tree::ptree root; + boost::property_tree::ptree blocksNode; // array of block strings + boost::property_tree::ptree txsNodes; // array of txs per block (array of array) + for (int blockIdx = 0; blockIdx < resp_struct.blocks.size(); blockIdx++) { + + // parse and validate block + cryptonote::block block; + if (cryptonote::parse_and_validate_block_from_blob(resp_struct.blocks[blockIdx].block, block)) { + + // add block node to blocks node + boost::property_tree::ptree blockNode; + blockNode.put("", cryptonote::obj_to_json_str(block)); // TODO: no pretty print + blocksNode.push_back(std::make_pair("", blockNode)); + } else { + throw std::runtime_error("failed to parse block blob at index " + std::to_string(blockIdx)); + } + + // parse and validate txs + boost::property_tree::ptree txsNode; + for (int txIdx = 0; txIdx < resp_struct.blocks[blockIdx].txs.size(); txIdx++) { + cryptonote::transaction tx; + if (cryptonote::parse_and_validate_tx_from_blob(resp_struct.blocks[blockIdx].txs[txIdx], tx)) { + + // add tx node to txs node + boost::property_tree::ptree txNode; + //std::cout << "PRUNED:\n" << MoneroUtils::get_pruned_tx_json(tx) << "\n"; + txNode.put("", MoneroUtils::get_pruned_tx_json(tx)); // TODO: no pretty print + txsNode.push_back(std::make_pair("", txNode)); + } else { + throw std::runtime_error("failed to parse tx blob at index " + std::to_string(txIdx)); + } + } + txsNodes.push_back(std::make_pair("", txsNode)); // array of array of transactions, one array per block + } + root.add_child("blocks", blocksNode); + root.add_child("txs", txsNodes); + root.put("status", resp_struct.status); + root.put("untrusted", resp_struct.untrusted); // TODO: loss of ints and bools + + // convert root to string // TODO: common utility with serial_bridge + std::stringstream ss; + boost::property_tree::write_json(ss, root, false/*pretty*/); + buff_json = ss.str(); +} diff --git a/src/utils/MoneroUtils.h b/src/utils/MoneroUtils.h new file mode 100644 index 0000000..3bcb837 --- /dev/null +++ b/src/utils/MoneroUtils.h @@ -0,0 +1,44 @@ +#ifndef MoneroUtils_h +#define MoneroUtils_h + +#include "cryptonote_basic/cryptonote_basic.h" +#include "serialization/keyvalue_serialization.h" // TODO: consolidate with other binary deps? +#include "storages/portable_storage.h" + +/** + * Collection of utilities for working with Monero's binary portable storage format. + */ +namespace MoneroUtils +{ + using namespace std; + using namespace boost; + using namespace cryptonote; + + /** + * TODO. + */ + void json_to_binary(const std::string &buff_json, std::string &buff_bin); + + /** + * TODO. + */ + void binary_to_json(const std::string &buff_bin, std::string &buff_json); + + /** + * TODO. + */ + void binary_blocks_to_json(const std::string &buff_bin, std::string &buff_json); + + /** + * Modified from core_rpc_server.cpp to return a string. + */ + static std::string get_pruned_tx_json(cryptonote::transaction &tx) + { + std::stringstream ss; + json_archive ar(ss); + bool r = tx.serialize_base(ar); + CHECK_AND_ASSERT_MES(r, std::string(), "Failed to serialize rct signatures base"); + return ss.str(); + } +} +#endif /* MoneroUtils_h */