diff --git a/src/MempoolStatus.cpp b/src/MempoolStatus.cpp index 2239b2f..380d087 100644 --- a/src/MempoolStatus.cpp +++ b/src/MempoolStatus.cpp @@ -35,48 +35,48 @@ MempoolStatus::start_mempool_status_thread() { uint64_t loop_index {0}; - // so that network status is checked every minute - uint64_t loop_index_divider = std::max(1, 60 / mempool_refresh_time); + // so that network status is checked every minute + uint64_t loop_index_divider = std::max(1, 60 / mempool_refresh_time); - while (true) - { + while (true) + { - // we just query network status every minute. No sense - // to do it as frequently as getting mempool data. - if (loop_index % loop_index_divider == 0) + // we just query network status every minute. No sense + // to do it as frequently as getting mempool data. + if (loop_index % loop_index_divider == 0) + { + if (!MempoolStatus::read_network_info()) { - if (!MempoolStatus::read_network_info()) - { - network_info local_copy = current_network_info; + network_info local_copy = current_network_info; - cerr << " Cant read network info "<< endl; + cerr << " Cant read network info "<< endl; - local_copy.current = false; + local_copy.current = false; - current_network_info = local_copy; - } - else - { - cout << "Current network info read, "; - loop_index = 0; - } + current_network_info = local_copy; } - - if (MempoolStatus::read_mempool()) + else { - vector current_mempool_txs = get_mempool_txs(); - - cout << "mempool status txs: " - << current_mempool_txs.size() - << endl; + cout << "Current network info read, "; + loop_index = 0; } + } + + if (MempoolStatus::read_mempool()) + { + vector current_mempool_txs = get_mempool_txs(); + + cout << "mempool status txs: " + << current_mempool_txs.size() + << endl; + } - // when we reach top of the blockchain, update - // the emission amount every minute. - boost::this_thread::sleep_for( - boost::chrono::seconds(mempool_refresh_time)); + // when we reach top of the blockchain, update + // the emission amount every minute. + boost::this_thread::sleep_for( + boost::chrono::seconds(mempool_refresh_time)); - ++loop_index; + ++loop_index; } // while (true) } @@ -84,7 +84,7 @@ MempoolStatus::start_mempool_status_thread() { cout << "Mempool status thread interrupted." << endl; return; - } + } }}; // m_thread = boost::thread{[]() @@ -137,7 +137,6 @@ MempoolStatus::read_mempool() return false; } - mempool_size_kB += _tx_info.blob_size; local_copy_of_mempool_txs.push_back(mempool_tx {tx_hash, tx}); diff --git a/src/tools.cpp b/src/tools.cpp index 446f41e..ac90da5 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -15,141 +15,141 @@ namespace xmreg * into crypto::secret_key or crypto::public_key * depending on the template argument. */ - template - bool - parse_str_secret_key(const string& key_str, T& secret_key) - { +template +bool +parse_str_secret_key(const string& key_str, T& secret_key) +{ - // hash and keys have same structure, so to parse string of - // a key, e.g., a view key, we can first parse it into the hash - // object using parse_hash256 function, and then copy the reslting - // hash data into secret key. - crypto::hash hash_; + // hash and keys have same structure, so to parse string of + // a key, e.g., a view key, we can first parse it into the hash + // object using parse_hash256 function, and then copy the reslting + // hash data into secret key. + crypto::hash hash_; - if(!parse_hash256(key_str, hash_)) - { - cerr << "Cant parse a key (e.g. viewkey): " << key_str << endl; - return false; - } + if(!parse_hash256(key_str, hash_)) + { + cerr << "Cant parse a key (e.g. viewkey): " << key_str << endl; + return false; + } - // crypto::hash and crypto::secret_key have basicly same - // structure. They both keep they key/hash as c-style char array - // of fixed size. Thus we can just copy data from hash - // to key - copy(begin(hash_.data), end(hash_.data), secret_key.data); + // crypto::hash and crypto::secret_key have basicly same + // structure. They both keep they key/hash as c-style char array + // of fixed size. Thus we can just copy data from hash + // to key + copy(begin(hash_.data), end(hash_.data), secret_key.data); - return true; - } + return true; +} // explicit instantiations of get template function - template bool parse_str_secret_key(const string& key_str, crypto::secret_key& secret_key); - template bool parse_str_secret_key(const string& key_str, crypto::public_key& secret_key); - template bool parse_str_secret_key(const string& key_str, crypto::hash& secret_key); +template bool parse_str_secret_key(const string& key_str, crypto::secret_key& secret_key); +template bool parse_str_secret_key(const string& key_str, crypto::public_key& secret_key); +template bool parse_str_secret_key(const string& key_str, crypto::hash& secret_key); /** - * Get transaction tx using given tx hash. Hash is represent as string here, - * so before we can tap into the blockchain, we need to pare it into - * crypto::hash object. - */ - bool - get_tx_pub_key_from_str_hash(Blockchain& core_storage, const string& hash_str, transaction& tx) - { - crypto::hash tx_hash; - parse_hash256(hash_str, tx_hash); - - try - { - // get transaction with given hash - tx = core_storage.get_db().get_tx(tx_hash); - } - catch (const TX_DNE& e) - { - cerr << e.what() << endl; - return false; - } +* Get transaction tx using given tx hash. Hash is represent as string here, +* so before we can tap into the blockchain, we need to pare it into +* crypto::hash object. +*/ +bool +get_tx_pub_key_from_str_hash(Blockchain& core_storage, const string& hash_str, transaction& tx) +{ + crypto::hash tx_hash; + parse_hash256(hash_str, tx_hash); - return true; + try + { + // get transaction with given hash + tx = core_storage.get_db().get_tx(tx_hash); } - -/** - * Parse monero address in a string form into - * cryptonote::account_public_address object - */ - bool - parse_str_address(const string& address_str, - address_parse_info& address_info, - bool testnet) + catch (const TX_DNE& e) { - - if (!get_account_address_from_str(address_info, testnet, address_str)) - { - cerr << "Error getting address: " << address_str << endl; - return false; - } - - return true; + cerr << e.what() << endl; + return false; } + return true; +} /** - * Return string representation of monero address - */ - string - print_address(const address_parse_info& address_info, bool testnet) +* Parse monero address in a string form into +* cryptonote::account_public_address object +*/ +bool +parse_str_address(const string& address_str, + address_parse_info& address_info, + bool testnet) +{ + + if (!get_account_address_from_str(address_info, testnet, address_str)) { - return "<" + get_account_address_as_str( - testnet, address_info.is_subaddress, address_info.address) - + ">"; + cerr << "Error getting address: " << address_str << endl; + return false; } - string - print_sig (const signature& sig) - { - stringstream ss; + return true; +} - ss << "c: <" << epee::string_tools::pod_to_hex(sig.c) << "> " - << "r: <" << epee::string_tools::pod_to_hex(sig.r) << ">"; - return ss.str(); - } +/** +* Return string representation of monero address +*/ +string +print_address(const address_parse_info& address_info, bool testnet) +{ + return "<" + get_account_address_as_str( + testnet, address_info.is_subaddress, address_info.address) + + ">"; +} + +string +print_sig (const signature& sig) +{ + stringstream ss; + + ss << "c: <" << epee::string_tools::pod_to_hex(sig.c) << "> " + << "r: <" << epee::string_tools::pod_to_hex(sig.r) << ">"; + + return ss.str(); +} /** - * Check if a character is a path seprator - */ - inline bool - is_separator(char c) - { - // default linux path separator - const char separator = PATH_SEPARARTOR; +* Check if a character is a path seprator +*/ +inline bool +is_separator(char c) +{ + // default linux path separator + const char separator = PATH_SEPARARTOR; - return c == separator; - } + return c == separator; +} /** - * Remove trailinig path separator. - */ - string - remove_trailing_path_separator(const string& in_path) - { - string new_string = in_path; - if (!new_string.empty() && is_separator(new_string[new_string.size() - 1])) - new_string.erase(new_string.size() - 1); - return new_string; - } +* Remove trailinig path separator. +*/ +string +remove_trailing_path_separator(const string& in_path) +{ + string new_string = in_path; + if (!new_string.empty() && is_separator(new_string[new_string.size() - 1])) + new_string.erase(new_string.size() - 1); + return new_string; +} - bf::path - remove_trailing_path_separator(const bf::path& in_path) - { +bf::path +remove_trailing_path_separator(const bf::path& in_path) +{ #ifdef WIN32 - std::wstring_convert, wchar_t> converter; - string path_str = converter.to_bytes(in_path.native()); + std::wstring_convert, wchar_t> converter; +string path_str = converter.to_bytes(in_path.native()); #else - string path_str = in_path.native(); + string path_str = in_path.native(); #endif - return bf::path(remove_trailing_path_separator(path_str)); - } + return bf::path(remove_trailing_path_separator(path_str)); +} //string //timestamp_to_str(time_t timestamp, const char* format) @@ -158,1381 +158,1108 @@ namespace xmreg //} - string - timestamp_to_str_gm(time_t timestamp, const char* format) - { - const time_t* t = ×tamp; +string +timestamp_to_str_gm(time_t timestamp, const char* format) +{ + const time_t* t = ×tamp; - const int TIME_LENGTH = 60; + const int TIME_LENGTH = 60; - char str_buff[TIME_LENGTH]; + char str_buff[TIME_LENGTH]; - std::tm tmp; - gmtime_r(t, &tmp); + std::tm tmp; + gmtime_r(t, &tmp); - size_t len; + size_t len; - len = std::strftime(str_buff, TIME_LENGTH, format, &tmp); + len = std::strftime(str_buff, TIME_LENGTH, format, &tmp); - return string(str_buff, len); - } + return string(str_buff, len); +} - ostream& - operator<< (ostream& os, const address_parse_info& addr_info) - { - os << get_account_address_as_str(false, addr_info.is_subaddress, addr_info.address); - return os; - } +ostream& +operator<< (ostream& os, const address_parse_info& addr_info) +{ + os << get_account_address_as_str(false, addr_info.is_subaddress, addr_info.address); + return os; +} /* - * Generate key_image of foran ith output - */ - bool - generate_key_image(const crypto::key_derivation& derivation, - const std::size_t i, - const crypto::secret_key& sec_key, - const crypto::public_key& pub_key, - crypto::key_image& key_img) - { - - cryptonote::keypair in_ephemeral; +* Generate key_image of foran ith output +*/ +bool +generate_key_image(const crypto::key_derivation& derivation, + const std::size_t i, + const crypto::secret_key& sec_key, + const crypto::public_key& pub_key, + crypto::key_image& key_img) +{ - if (!crypto::derive_public_key(derivation, i, - pub_key, - in_ephemeral.pub)) - { - cerr << "Error generating publick key " << pub_key << endl; - return false; - } + cryptonote::keypair in_ephemeral; - try - { + if (!crypto::derive_public_key(derivation, i, + pub_key, + in_ephemeral.pub)) + { + cerr << "Error generating publick key " << pub_key << endl; + return false; + } - crypto::derive_secret_key(derivation, i, - sec_key, - in_ephemeral.sec); - } - catch(const std::exception& e) - { - cerr << "Error generate secret image: " << e.what() << endl; - return false; - } + try + { + crypto::derive_secret_key(derivation, i, + sec_key, + in_ephemeral.sec); + } + catch(const std::exception& e) + { + cerr << "Error generate secret image: " << e.what() << endl; + return false; + } - try - { - crypto::generate_key_image(in_ephemeral.pub, - in_ephemeral.sec, - key_img); - } - catch(const std::exception& e) - { - cerr << "Error generate key image: " << e.what() << endl; - return false; - } - return true; + try + { + crypto::generate_key_image(in_ephemeral.pub, + in_ephemeral.sec, + key_img); + } + catch(const std::exception& e) + { + cerr << "Error generate key image: " << e.what() << endl; + return false; } + return true; +} - string - get_default_lmdb_folder(bool testnet) - { - // default path to monero folder - // on linux this is /home//.bitmonero - string default_monero_dir = tools::get_default_data_dir(); - if (testnet) - default_monero_dir += "/testnet"; +string +get_default_lmdb_folder(bool testnet) +{ + // default path to monero folder + // on linux this is /home//.bitmonero + string default_monero_dir = tools::get_default_data_dir(); + if (testnet) + default_monero_dir += "/testnet"; - // the default folder of the lmdb blockchain database - // is therefore as follows - return default_monero_dir + string("/lmdb"); - } + + // the default folder of the lmdb blockchain database + // is therefore as follows + return default_monero_dir + string("/lmdb"); +} /* - * Ge blockchain exception from command line option - * - * If not given, provide default path - */ - bool - get_blockchain_path(const boost::optional& bc_path, - bf::path& blockchain_path, - bool testnet) +* Ge blockchain exception from command line option +* +* If not given, provide default path +*/ +bool +get_blockchain_path(const boost::optional& bc_path, + bf::path& blockchain_path, + bool testnet) +{ + // the default folder of the lmdb blockchain database + string default_lmdb_dir = xmreg::get_default_lmdb_folder(testnet); + + blockchain_path = bc_path + ? bf::path(*bc_path) + : bf::path(default_lmdb_dir); + + if (!bf::is_directory(blockchain_path)) { - // the default folder of the lmdb blockchain database - string default_lmdb_dir = xmreg::get_default_lmdb_folder(testnet); + cerr << "Given path \"" << blockchain_path << "\" " + << "is not a folder or does not exist" << " " + << endl; + + return false; + } - blockchain_path = bc_path - ? bf::path(*bc_path) - : bf::path(default_lmdb_dir); + blockchain_path = xmreg::remove_trailing_path_separator(blockchain_path); - if (!bf::is_directory(blockchain_path)) - { - cerr << "Given path \"" << blockchain_path << "\" " - << "is not a folder or does not exist" << " " - << endl; + return true; +} - return false; - } - blockchain_path = xmreg::remove_trailing_path_separator(blockchain_path); +uint64_t +sum_money_in_outputs(const transaction& tx) +{ + uint64_t sum_xmr {0}; - return true; + for (const tx_out& txout: tx.vout) + { + sum_xmr += txout.amount; } + return sum_xmr; +} - uint64_t - sum_money_in_outputs(const transaction& tx) - { - uint64_t sum_xmr {0}; +pair +sum_money_in_outputs(const string& json_str) +{ + pair sum_xmr {0, 0}; - for (const tx_out& txout: tx.vout) - { - sum_xmr += txout.amount; - } + json j; + try + { + j = json::parse( json_str); + } + catch (std::invalid_argument& e) + { + cerr << "sum_money_in_outputs: " << e.what() << endl; return sum_xmr; } - pair - sum_money_in_outputs(const string& json_str) + for (json& vout: j["vout"]) { - pair sum_xmr {0, 0}; + sum_xmr.first += vout["amount"].get(); + ++sum_xmr.second; + } - json j; - try - { - j = json::parse( json_str); - } - catch (std::invalid_argument& e) - { - cerr << "sum_money_in_outputs: " << e.what() << endl; - return sum_xmr; - } + return sum_xmr; +}; - for (json& vout: j["vout"]) - { - sum_xmr.first += vout["amount"].get(); - ++sum_xmr.second; - } +pair +sum_money_in_outputs(const json& _json) +{ + pair sum_xmr {0ULL, 0ULL}; + for (const json& vout: _json["vout"]) + { + sum_xmr.first += vout["amount"].get(); + ++sum_xmr.second; + } - return sum_xmr; - }; + return sum_xmr; +}; - pair - sum_money_in_outputs(const json& _json) - { - pair sum_xmr {0ULL, 0ULL}; - for (const json& vout: _json["vout"]) - { - sum_xmr.first += vout["amount"].get(); - ++sum_xmr.second; - } +array +summary_of_in_out_rct( + const transaction& tx, + vector>& output_pub_keys, + vector& input_key_imgs) +{ - return sum_xmr; - }; + uint64_t xmr_outputs {0}; + uint64_t xmr_inputs {0}; + uint64_t mixin_no {0}; + uint64_t num_nonrct_inputs {0}; - array - summary_of_in_out_rct( - const transaction& tx, - vector>& output_pub_keys, - vector& input_key_imgs) + for (const tx_out& txout: tx.vout) { + if (txout.target.type() != typeid(txout_to_key)) + { + // push empty pair. + output_pub_keys.push_back(pair{}); + continue; + } - uint64_t xmr_outputs {0}; - uint64_t xmr_inputs {0}; - uint64_t mixin_no {0}; - uint64_t num_nonrct_inputs {0}; + // get tx input key + const txout_to_key& txout_key + = boost::get(txout.target); + output_pub_keys.push_back(make_pair(txout_key, txout.amount)); - for (const tx_out& txout: tx.vout) - { - if (txout.target.type() != typeid(txout_to_key)) - { - // push empty pair. - output_pub_keys.push_back(pair{}); - continue; - } + xmr_outputs += txout.amount; + } - // get tx input key - const txout_to_key& txout_key - = boost::get(txout.target); + size_t input_no = tx.vin.size(); - output_pub_keys.push_back(make_pair(txout_key, txout.amount)); + for (size_t i = 0; i < input_no; ++i) + { - xmr_outputs += txout.amount; + if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) + { + continue; } - size_t input_no = tx.vin.size(); + // get tx input key + const cryptonote::txin_to_key& tx_in_to_key + = boost::get(tx.vin[i]); - for (size_t i = 0; i < input_no; ++i) - { - - if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) - { - continue; - } + xmr_inputs += tx_in_to_key.amount; - // get tx input key - const cryptonote::txin_to_key& tx_in_to_key - = boost::get(tx.vin[i]); + if (tx_in_to_key.amount != 0) + { + ++num_nonrct_inputs; + } - xmr_inputs += tx_in_to_key.amount; + if (mixin_no == 0) + { + mixin_no = tx_in_to_key.key_offsets.size(); + } - if (tx_in_to_key.amount != 0) - { - ++num_nonrct_inputs; - } + input_key_imgs.push_back(tx_in_to_key); - if (mixin_no == 0) - { - mixin_no = tx_in_to_key.key_offsets.size(); - } + } // for (size_t i = 0; i < input_no; ++i) - input_key_imgs.push_back(tx_in_to_key); - } // for (size_t i = 0; i < input_no; ++i) + return {xmr_outputs, xmr_inputs, mixin_no, num_nonrct_inputs}; +}; - return {xmr_outputs, xmr_inputs, mixin_no, num_nonrct_inputs}; - }; +// this version for mempool txs from json +array +summary_of_in_out_rct(const json& _json) +{ + uint64_t xmr_outputs {0}; + uint64_t xmr_inputs {0}; + uint64_t no_outputs {0}; + uint64_t no_inputs {0}; + uint64_t mixin_no {0}; + uint64_t num_nonrct_inputs {0}; + + for (const json& vout: _json["vout"]) + { + xmr_outputs += vout["amount"].get(); + } + no_outputs = _json["vout"].size(); -// this version for mempool txs from json - array - summary_of_in_out_rct(const json& _json) + for (const json& vin: _json["vin"]) { - uint64_t xmr_outputs {0}; - uint64_t xmr_inputs {0}; - uint64_t no_outputs {0}; - uint64_t no_inputs {0}; - uint64_t mixin_no {0}; - uint64_t num_nonrct_inputs {0}; - - for (const json& vout: _json["vout"]) - { - xmr_outputs += vout["amount"].get(); - } + uint64_t amount = vin["key"]["amount"].get(); - no_outputs = _json["vout"].size(); + xmr_inputs += amount; - for (const json& vin: _json["vin"]) - { - uint64_t amount = vin["key"]["amount"].get(); + if (amount != 0) + ++num_nonrct_inputs; + } - xmr_inputs += amount; + no_inputs = _json["vin"].size(); - if (amount != 0) - ++num_nonrct_inputs; - } + mixin_no = _json["vin"].at(0)["key"]["key_offsets"].size() - 1; - no_inputs = _json["vin"].size(); + return {xmr_outputs, xmr_inputs, no_outputs, no_inputs, mixin_no, num_nonrct_inputs}; +}; - mixin_no = _json["vin"].at(0)["key"]["key_offsets"].size() - 1; - return {xmr_outputs, xmr_inputs, no_outputs, no_inputs, mixin_no, num_nonrct_inputs}; - }; +uint64_t +sum_money_in_inputs(const transaction& tx) +{ + uint64_t sum_xmr {0}; + size_t input_no = tx.vin.size(); - uint64_t - sum_money_in_inputs(const transaction& tx) + for (size_t i = 0; i < input_no; ++i) { - uint64_t sum_xmr {0}; - size_t input_no = tx.vin.size(); - - for (size_t i = 0; i < input_no; ++i) + if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) { + continue; + } - if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) - { - continue; - } + // get tx input key + const cryptonote::txin_to_key& tx_in_to_key + = boost::get(tx.vin[i]); - // get tx input key - const cryptonote::txin_to_key& tx_in_to_key - = boost::get(tx.vin[i]); + sum_xmr += tx_in_to_key.amount; + } - sum_xmr += tx_in_to_key.amount; - } + return sum_xmr; +} + +pair +sum_money_in_inputs(const string& json_str) +{ + pair sum_xmr {0, 0}; + json j; + try + { + j = json::parse( json_str); + } + catch (std::invalid_argument& e) + { + cerr << "sum_money_in_outputs: " << e.what() << endl; return sum_xmr; } - pair - sum_money_in_inputs(const string& json_str) + for (json& vin: j["vin"]) { - pair sum_xmr {0, 0}; - - json j; - try - { - j = json::parse( json_str); - } - catch (std::invalid_argument& e) - { - cerr << "sum_money_in_outputs: " << e.what() << endl; - return sum_xmr; - } + sum_xmr.first += vin["key"]["amount"].get(); + ++sum_xmr.second; + } - for (json& vin: j["vin"]) - { - sum_xmr.first += vin["key"]["amount"].get(); - ++sum_xmr.second; - } + return sum_xmr; +}; - return sum_xmr; - }; +pair +sum_money_in_inputs(const json& _json) +{ + pair sum_xmr {0, 0}; - pair - sum_money_in_inputs(const json& _json) + for (const json& vin: _json["vin"]) { - pair sum_xmr {0, 0}; + sum_xmr.first += vin["key"]["amount"].get(); + ++sum_xmr.second; + } - for (const json& vin: _json["vin"]) - { - sum_xmr.first += vin["key"]["amount"].get(); - ++sum_xmr.second; - } + return sum_xmr; +}; - return sum_xmr; - }; +uint64_t +count_nonrct_inputs(const transaction& tx) +{ + uint64_t num {0}; - uint64_t - count_nonrct_inputs(const transaction& tx) - { - uint64_t num {0}; + size_t input_no = tx.vin.size(); - size_t input_no = tx.vin.size(); + for (size_t i = 0; i < input_no; ++i) + { - for (size_t i = 0; i < input_no; ++i) + if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) { + continue; + } - if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) - { - continue; - } + // get tx input key + const cryptonote::txin_to_key& tx_in_to_key + = boost::get(tx.vin[i]); - // get tx input key - const cryptonote::txin_to_key& tx_in_to_key - = boost::get(tx.vin[i]); + if (tx_in_to_key.amount != 0) + ++num; + } - if (tx_in_to_key.amount != 0) - ++num; - } + return num; +} + +uint64_t +count_nonrct_inputs(const string& json_str) +{ + uint64_t num {0}; + json j; + try + { + j = json::parse( json_str); + } + catch (std::invalid_argument& e) + { + cerr << "count_nonrct_inputs: " << e.what() << endl; return num; } - uint64_t - count_nonrct_inputs(const string& json_str) + for (json& vin: j["vin"]) { - uint64_t num {0}; - - json j; - try - { - j = json::parse( json_str); - } - catch (std::invalid_argument& e) - { - cerr << "count_nonrct_inputs: " << e.what() << endl; - return num; - } + uint64_t amount = vin["key"]["amount"].get(); + if (amount != 0) + ++num; + } - for (json& vin: j["vin"]) - { - uint64_t amount = vin["key"]["amount"].get(); - if (amount != 0) - ++num; - } + return num; +}; - return num; - }; +uint64_t +count_nonrct_inputs(const json& _json) +{ + uint64_t num {0}; - uint64_t - count_nonrct_inputs(const json& _json) + for (const json& vin: _json["vin"]) { - uint64_t num {0}; + uint64_t amount = vin["key"]["amount"].get(); + if (amount != 0) + ++num; + } - for (const json& vin: _json["vin"]) - { - uint64_t amount = vin["key"]["amount"].get(); - if (amount != 0) - ++num; - } + return num; +}; - return num; - }; +array +sum_money_in_tx(const transaction& tx) +{ + array sum_xmr; - array - sum_money_in_tx(const transaction& tx) - { - array sum_xmr; + sum_xmr[0] = sum_money_in_inputs(tx); + sum_xmr[1] = sum_money_in_outputs(tx); - sum_xmr[0] = sum_money_in_inputs(tx); - sum_xmr[1] = sum_money_in_outputs(tx); + return sum_xmr; +}; - return sum_xmr; - }; +array +sum_money_in_txs(const vector& txs) +{ + array sum_xmr {0,0}; - array - sum_money_in_txs(const vector& txs) + for (const transaction& tx: txs) { - array sum_xmr {0,0}; + sum_xmr[0] += sum_money_in_inputs(tx); + sum_xmr[1] += sum_money_in_outputs(tx); + } - for (const transaction& tx: txs) - { - sum_xmr[0] += sum_money_in_inputs(tx); - sum_xmr[1] += sum_money_in_outputs(tx); - } + return sum_xmr; +}; - return sum_xmr; - }; +uint64_t +sum_fees_in_txs(const vector& txs) +{ + uint64_t fees_sum {0}; - uint64_t - sum_fees_in_txs(const vector& txs) + for (const transaction& tx: txs) { - uint64_t fees_sum {0}; + fees_sum += get_tx_fee(tx); + } - for (const transaction& tx: txs) - { - fees_sum += get_tx_fee(tx); - } + return fees_sum; +} - return fees_sum; - } +vector> +get_ouputs(const transaction& tx) +{ + vector> outputs; - vector> - get_ouputs(const transaction& tx) + for (const tx_out& txout: tx.vout) { - vector> outputs; - - for (const tx_out& txout: tx.vout) + if (txout.target.type() != typeid(txout_to_key)) { - if (txout.target.type() != typeid(txout_to_key)) - { - // push empty pair. - outputs.push_back(pair{}); - continue; - } + // push empty pair. + outputs.push_back(pair{}); + continue; + } - // get tx input key - const txout_to_key& txout_key - = boost::get(txout.target); + // get tx input key + const txout_to_key& txout_key + = boost::get(txout.target); - outputs.push_back(make_pair(txout_key, txout.amount)); - } + outputs.push_back(make_pair(txout_key, txout.amount)); + } + + return outputs; - return outputs; +}; - }; +vector> +get_ouputs_tuple(const transaction& tx) +{ + vector> outputs; - vector> - get_ouputs_tuple(const transaction& tx) + for (uint64_t n = 0; n < tx.vout.size(); ++n) { - vector> outputs; - for (uint64_t n = 0; n < tx.vout.size(); ++n) + if (tx.vout[n].target.type() != typeid(txout_to_key)) { + continue; + } - if (tx.vout[n].target.type() != typeid(txout_to_key)) - { - continue; - } + // get tx input key + const txout_to_key& txout_key + = boost::get(tx.vout[n].target); - // get tx input key - const txout_to_key& txout_key - = boost::get(tx.vout[n].target); + outputs.push_back(make_tuple(txout_key, tx.vout[n].amount, n)); + } - outputs.push_back(make_tuple(txout_key, tx.vout[n].amount, n)); - } + return outputs; +}; + +uint64_t +get_mixin_no(const transaction& tx) +{ + uint64_t mixin_no {0}; - return outputs; - }; + size_t input_no = tx.vin.size(); - uint64_t - get_mixin_no(const transaction& tx) + for (size_t i = 0; i < input_no; ++i) { - uint64_t mixin_no {0}; - - size_t input_no = tx.vin.size(); - for (size_t i = 0; i < input_no; ++i) + if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) { + continue; + } - if(tx.vin[i].type() != typeid(cryptonote::txin_to_key)) - { - continue; - } - - // get tx input key - const txin_to_key& tx_in_to_key - = boost::get(tx.vin[i]); + // get tx input key + const txin_to_key& tx_in_to_key + = boost::get(tx.vin[i]); - mixin_no = tx_in_to_key.key_offsets.size(); + mixin_no = tx_in_to_key.key_offsets.size(); - // look for first mixin number. - // all inputs in a single transaction have same number - if (mixin_no > 0) - { - break; - } + // look for first mixin number. + // all inputs in a single transaction have same number + if (mixin_no > 0) + { + break; } - - return mixin_no; } - vector - get_mixin_no(const string& json_str) - { - vector mixin_no; - json j; + return mixin_no; +} +vector +get_mixin_no(const string& json_str) +{ + vector mixin_no; - try - { - j = json::parse(json_str); + json j; - mixin_no.push_back(j["vin"].at(0)["key"]["key_offsets"].size()); - } - catch (std::invalid_argument& e) - { - cerr << "get_mixin_no: " << e.what() << endl; - return mixin_no; - } + try + { + j = json::parse(json_str); - return mixin_no; + mixin_no.push_back(j["vin"].at(0)["key"]["key_offsets"].size()); } - - vector - get_mixin_no(const json& _json) + catch (std::invalid_argument& e) { - vector mixin_no; - - mixin_no.push_back(_json["vin"].at(0)["key"]["key_offsets"].size()); - + cerr << "get_mixin_no: " << e.what() << endl; return mixin_no; } + return mixin_no; +} +vector +get_mixin_no(const json& _json) +{ + vector mixin_no; - vector - get_mixin_no_in_txs(const vector& txs) - { - vector mixin_no; + mixin_no.push_back(_json["vin"].at(0)["key"]["key_offsets"].size()); + + return mixin_no; +} - for (const transaction& tx: txs) - { - mixin_no.push_back(get_mixin_no(tx)); - } - return mixin_no; - } +vector +get_mixin_no_in_txs(const vector& txs) +{ + vector mixin_no; - vector - get_key_images(const transaction& tx) + for (const transaction& tx: txs) { - vector key_images; + mixin_no.push_back(get_mixin_no(tx)); + } - size_t input_no = tx.vin.size(); + return mixin_no; +} - for (size_t i = 0; i < input_no; ++i) - { - if(tx.vin[i].type() != typeid(txin_to_key)) - { - continue; - } +vector +get_key_images(const transaction& tx) +{ + vector key_images; - // get tx input key - const txin_to_key& tx_in_to_key - = boost::get(tx.vin[i]); + size_t input_no = tx.vin.size(); - key_images.push_back(tx_in_to_key); - } + for (size_t i = 0; i < input_no; ++i) + { - return key_images; - } + if(tx.vin[i].type() != typeid(txin_to_key)) + { + continue; + } + // get tx input key + const txin_to_key& tx_in_to_key + = boost::get(tx.vin[i]); - bool - get_payment_id(const vector& extra, - crypto::hash& payment_id, - crypto::hash8& payment_id8) - { - payment_id = null_hash; - payment_id8 = null_hash8; + key_images.push_back(tx_in_to_key); + } - std::vector tx_extra_fields; + return key_images; +} - if(!parse_tx_extra(extra, tx_extra_fields)) - { - return false; - } - tx_extra_nonce extra_nonce; +bool +get_payment_id(const vector& extra, + crypto::hash& payment_id, + crypto::hash8& payment_id8) +{ + payment_id = null_hash; + payment_id8 = null_hash8; - if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) - { - // first check for encrypted id and then for normal one - if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) - { - return true; - } - else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) - { - return true; - } - } + std::vector tx_extra_fields; + if(!parse_tx_extra(extra, tx_extra_fields)) + { return false; } + tx_extra_nonce extra_nonce; - bool - get_payment_id(const transaction& tx, - crypto::hash& payment_id, - crypto::hash8& payment_id8) + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) { - return get_payment_id(tx.extra, payment_id, payment_id8); + // first check for encrypted id and then for normal one + if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) + { + return true; + } + else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + { + return true; + } } + return false; +} - array - timestamp_difference(uint64_t t1, uint64_t t2) - { - uint64_t timestamp_diff = t1 - t2; +bool +get_payment_id(const transaction& tx, + crypto::hash& payment_id, + crypto::hash8& payment_id8) +{ + return get_payment_id(tx.extra, payment_id, payment_id8); +} - // calculate difference of timestamps from current block to the mixin one - if (t2 > t1) - { - timestamp_diff = t2 - t1; - } - uint64_t time_diff_years = timestamp_diff / 31536000; +array +timestamp_difference(uint64_t t1, uint64_t t2) +{ - timestamp_diff -= time_diff_years * 31536000; + uint64_t timestamp_diff = t1 - t2; - uint64_t time_diff_days = timestamp_diff / 86400; + // calculate difference of timestamps from current block to the mixin one + if (t2 > t1) + { + timestamp_diff = t2 - t1; + } - timestamp_diff -= time_diff_days * 86400; + uint64_t time_diff_years = timestamp_diff / 31536000; - uint64_t time_diff_hours = timestamp_diff / 3600; + timestamp_diff -= time_diff_years * 31536000; - timestamp_diff -= time_diff_hours * 3600; + uint64_t time_diff_days = timestamp_diff / 86400; - uint64_t time_diff_minutes = timestamp_diff / 60; + timestamp_diff -= time_diff_days * 86400; - timestamp_diff -= time_diff_minutes * 60; + uint64_t time_diff_hours = timestamp_diff / 3600; - uint64_t time_diff_seconds = timestamp_diff ; + timestamp_diff -= time_diff_hours * 3600; - return array {time_diff_years, time_diff_days, - time_diff_hours, time_diff_minutes, - time_diff_seconds}; + uint64_t time_diff_minutes = timestamp_diff / 60; - }; + timestamp_diff -= time_diff_minutes * 60; + uint64_t time_diff_seconds = timestamp_diff ; - string - read(string filename) - { - if (!bf::exists(bf::path(filename))) - { - cerr << "File does not exist: " << filename << endl; - return string(); - } + return array {time_diff_years, time_diff_days, + time_diff_hours, time_diff_minutes, + time_diff_seconds}; + +}; - std::ifstream t(filename); - return string(std::istreambuf_iterator(t), - std::istreambuf_iterator()); - } - pair - timestamps_time_scale(const vector& timestamps, - uint64_t timeN, - uint64_t resolution, - uint64_t time0) +string +read(string filename) +{ + if (!bf::exists(bf::path(filename))) { - string empty_time = string(resolution, '_'); + cerr << "File does not exist: " << filename << endl; + return string(); + } - size_t time_axis_length = empty_time.size(); + std::ifstream t(filename); + return string(std::istreambuf_iterator(t), + std::istreambuf_iterator()); +} - uint64_t interval_length = timeN-time0; +pair +timestamps_time_scale(const vector& timestamps, + uint64_t timeN, + uint64_t resolution, + uint64_t time0) +{ + string empty_time = string(resolution, '_'); - double scale = double(interval_length) / double(time_axis_length); + size_t time_axis_length = empty_time.size(); - for (const auto& timestamp: timestamps) - { + uint64_t interval_length = timeN-time0; - if (timestamp < time0 || timestamp > timeN) - { - cout << "Out of range" << endl; - continue; - } + double scale = double(interval_length) / double(time_axis_length); - uint64_t timestamp_place = double(timestamp-time0) - / double(interval_length)*(time_axis_length - 1); + for (const auto& timestamp: timestamps) + { - empty_time[timestamp_place + 1] = '*'; + if (timestamp < time0 || timestamp > timeN) + { + cout << "Out of range" << endl; + continue; } - return make_pair(empty_time, scale); + uint64_t timestamp_place = double(timestamp-time0) + / double(interval_length)*(time_axis_length - 1); + + empty_time[timestamp_place + 1] = '*'; } - bool - decode_ringct(const rct::rctSig& rv, - const crypto::public_key pub, - const crypto::secret_key &sec, - unsigned int i, - rct::key & mask, - uint64_t & amount) - { - crypto::key_derivation derivation; + return make_pair(empty_time, scale); +} - bool r = crypto::generate_key_derivation(pub, sec, derivation); +bool +decode_ringct(const rct::rctSig& rv, + const crypto::public_key pub, + const crypto::secret_key &sec, + unsigned int i, + rct::key & mask, + uint64_t & amount) +{ + crypto::key_derivation derivation; - if (!r) - { - cerr <<"Failed to generate key derivation to decode rct output " << i << endl; - return false; - } + bool r = crypto::generate_key_derivation(pub, sec, derivation); - return decode_ringct(rv, derivation, i, mask, amount); + if (!r) + { + cerr <<"Failed to generate key derivation to decode rct output " << i << endl; + return false; } - bool - decode_ringct(rct::rctSig const& rv, - crypto::key_derivation const& derivation, - unsigned int i, - rct::key& mask, - uint64_t& amount) + return decode_ringct(rv, derivation, i, mask, amount); +} + +bool +decode_ringct(rct::rctSig const& rv, + crypto::key_derivation const& derivation, + unsigned int i, + rct::key& mask, + uint64_t& amount) +{ + try { - try - { - crypto::secret_key scalar1; + crypto::secret_key scalar1; - crypto::derivation_to_scalar(derivation, i, scalar1); + crypto::derivation_to_scalar(derivation, i, scalar1); - switch (rv.type) - { - case rct::RCTTypeSimple: - case rct::RCTTypeSimpleBulletproof: - amount = rct::decodeRctSimple(rv, - rct::sk2rct(scalar1), - i, - mask); - break; - case rct::RCTTypeFull: - case rct::RCTTypeFullBulletproof: - amount = rct::decodeRct(rv, - rct::sk2rct(scalar1), - i, - mask); - break; - default: - cerr << "Unsupported rct type: " << rv.type << '\n'; - return false; - } - } - catch (...) + switch (rv.type) { - cerr << "Failed to decode input " << i << '\n'; - return false; + case rct::RCTTypeSimple: + case rct::RCTTypeSimpleBulletproof: + amount = rct::decodeRctSimple(rv, + rct::sk2rct(scalar1), + i, + mask); + break; + case rct::RCTTypeFull: + case rct::RCTTypeFullBulletproof: + amount = rct::decodeRct(rv, + rct::sk2rct(scalar1), + i, + mask); + break; + default: + cerr << "Unsupported rct type: " << rv.type << '\n'; + return false; } - - return true; } + catch (...) + { + cerr << "Failed to decode input " << i << '\n'; + return false; + } + + return true; +} - bool - url_decode(const std::string& in, std::string& out) +bool +url_decode(const std::string& in, std::string& out) +{ + out.clear(); + out.reserve(in.size()); + for (std::size_t i = 0; i < in.size(); ++i) { - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) + if (in[i] == '%') { - if (in[i] == '%') + if (i + 3 <= in.size()) { - if (i + 3 <= in.size()) + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + if (is >> std::hex >> value) { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast(value); - i += 2; - } - else - { - return false; - } + out += static_cast(value); + i += 2; } else { return false; } } - else if (in[i] == '+') - { - out += ' '; - } else { - out += in[i]; + return false; } } - return true; + else if (in[i] == '+') + { + out += ' '; + } + else + { + out += in[i]; + } } + return true; +} - map - parse_crow_post_data(const string& req_body) - { - map body; +map +parse_crow_post_data(const string& req_body) +{ + map body; - vector vec; - string tmp; - bool result = url_decode(req_body, tmp); - if (result) + vector vec; + string tmp; + bool result = url_decode(req_body, tmp); + if (result) + { + boost::algorithm::split(vec, tmp, [](char x) {return x == '&'; }); + for(auto &it : vec) { - boost::algorithm::split(vec, tmp, [](char x) {return x == '&'; }); - for(auto &it : vec) + auto pos = it.find("="); + if (pos != string::npos) { - auto pos = it.find("="); - if (pos != string::npos) - { - body[it.substr(0, pos)] = it.substr(pos + 1); - } - else - { - break; - } + body[it.substr(0, pos)] = it.substr(pos + 1); + } + else + { + break; } } - return body; } + return body; +} // from wallet2::decrypt - string - decrypt(const std::string &ciphertext, - const crypto::secret_key &skey, - bool authenticated) - { - - const size_t prefix_size = sizeof(chacha8_iv) - + (authenticated ? sizeof(crypto::signature) : 0); - if (ciphertext.size() < prefix_size) - { - cerr << "Unexpected ciphertext size" << endl; - return {}; - } +string +decrypt(const std::string &ciphertext, + const crypto::secret_key &skey, + bool authenticated) +{ - crypto::chacha8_key key; - crypto::generate_chacha8_key(&skey, sizeof(skey), key); + const size_t prefix_size = sizeof(chacha8_iv) + + (authenticated ? sizeof(crypto::signature) : 0); + if (ciphertext.size() < prefix_size) + { + cerr << "Unexpected ciphertext size" << endl; + return {}; + } - const crypto::chacha8_iv &iv = *(const crypto::chacha8_iv*)&ciphertext[0]; + crypto::chacha8_key key; + crypto::generate_chacha8_key(&skey, sizeof(skey), key); - std::string plaintext; + const crypto::chacha8_iv &iv = *(const crypto::chacha8_iv*)&ciphertext[0]; - plaintext.resize(ciphertext.size() - prefix_size); + std::string plaintext; - if (authenticated) - { - crypto::hash hash; - crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash); - crypto::public_key pkey; - crypto::secret_key_to_public_key(skey, pkey); + plaintext.resize(ciphertext.size() - prefix_size); - const crypto::signature &signature = - *(const crypto::signature*)&ciphertext[ciphertext.size() - - sizeof(crypto::signature)]; + if (authenticated) + { + crypto::hash hash; + crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash); + crypto::public_key pkey; + crypto::secret_key_to_public_key(skey, pkey); - if (!crypto::check_signature(hash, pkey, signature)) - { - cerr << "Failed to authenticate criphertext" << endl; - return {}; - } + const crypto::signature &signature = + *(const crypto::signature*)&ciphertext[ciphertext.size() + - sizeof(crypto::signature)]; + if (!crypto::check_signature(hash, pkey, signature)) + { + cerr << "Failed to authenticate criphertext" << endl; + return {}; } - crypto::chacha8(ciphertext.data() + sizeof(iv), - ciphertext.size() - prefix_size, - key, iv, &plaintext[0]); - - return plaintext; } + crypto::chacha8(ciphertext.data() + sizeof(iv), + ciphertext.size() - prefix_size, + key, iv, &plaintext[0]); + + return plaintext; +} + // based on // crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const - public_key - get_tx_pub_key_from_received_outs(const transaction &tx) - { - std::vector tx_extra_fields; - - if(!parse_tx_extra(tx.extra, tx_extra_fields)) - { - // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key - } +public_key +get_tx_pub_key_from_received_outs(const transaction &tx) +{ + std::vector tx_extra_fields; - // Due to a previous bug, there might be more than one tx pubkey in extra, one being - // the result of a previously discarded signature. - // For speed, since scanning for outputs is a slow process, we check whether extra - // contains more than one pubkey. If not, the first one is returned. If yes, they're - // checked for whether they yield at least one output - tx_extra_pub_key pub_key_field; + if(!parse_tx_extra(tx.extra, tx_extra_fields)) + { + // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key + } - if (!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 0)) - { - return null_pkey; - } + // Due to a previous bug, there might be more than one tx pubkey in extra, one being + // the result of a previously discarded signature. + // For speed, since scanning for outputs is a slow process, we check whether extra + // contains more than one pubkey. If not, the first one is returned. If yes, they're + // checked for whether they yield at least one output + tx_extra_pub_key pub_key_field; - public_key tx_pub_key = pub_key_field.pub_key; + if (!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 0)) + { + return null_pkey; + } - bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1); + public_key tx_pub_key = pub_key_field.pub_key; - if (!two_found) - { - // easy case, just one found - return tx_pub_key; - } - else - { - // just return second one if there are two. - // this does not require private view key, as - // its not needed for my use case. - return pub_key_field.pub_key; - } + bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1); - return null_pkey; + if (!two_found) + { + // easy case, just one found + return tx_pub_key; } + else + { + // just return second one if there are two. + // this does not require private view key, as + // its not needed for my use case. + return pub_key_field.pub_key; + } + + return null_pkey; +} /** * Check if given output (specified by output_index) * belongs is ours based * on our private view key and public spend key */ - bool - is_output_ours(const size_t& output_index, - const transaction& tx, - const public_key& pub_tx_key, - const secret_key& private_view_key, - const public_key& public_spend_key) - { - // public transaction key is combined with our viewkey - // to create, so called, derived key. - key_derivation derivation; - - if (!generate_key_derivation(pub_tx_key, private_view_key, derivation)) - { - cerr << "Cant get dervied key for: " << "\n" - << "pub_tx_key: " << pub_tx_key << " and " - << "prv_view_key" << private_view_key << endl; - - return false; - } - - - // get the tx output public key - // that normally would be generated for us, - // if someone had sent us some xmr. - public_key pubkey; - - derive_public_key(derivation, - output_index, - public_spend_key, - pubkey); - - //cout << "\n" << tx.vout.size() << " " << output_index << endl; - - // get tx output public key - const txout_to_key tx_out_to_key - = boost::get(tx.vout[output_index].target); - +bool +is_output_ours(const size_t& output_index, + const transaction& tx, + const public_key& pub_tx_key, + const secret_key& private_view_key, + const public_key& public_spend_key) +{ + // public transaction key is combined with our viewkey + // to create, so called, derived key. + key_derivation derivation; - if (tx_out_to_key.key == pubkey) - { - return true; - } + if (!generate_key_derivation(pub_tx_key, private_view_key, derivation)) + { + cerr << "Cant get dervied key for: " << "\n" + << "pub_tx_key: " << pub_tx_key << " and " + << "prv_view_key" << private_view_key << endl; return false; } - bool - get_real_output_for_key_image(const key_image& ki, - const transaction& tx, - const secret_key& private_view_key, - const public_key& public_spend_key, - uint64_t output_idx, - public_key output_pub_key) - { + // get the tx output public key + // that normally would be generated for us, + // if someone had sent us some xmr. + public_key pubkey; + derive_public_key(derivation, + output_index, + public_spend_key, + pubkey); + //cout << "\n" << tx.vout.size() << " " << output_index << endl; - return false; - } + // get tx output public key + const txout_to_key tx_out_to_key + = boost::get(tx.vout[output_index].target); - bool - make_tx_from_json(const string& json_str, transaction& tx) + if (tx_out_to_key.key == pubkey) { - json j; - - try - { - j = json::parse(json_str); - } - catch (std::invalid_argument& e) - { - cerr << "make_tx_from_json: cant parse json string: " << e.what() << endl; - return false; - } - - - cout << "\n\n j.dump()" << j.dump(4) << '\n'; + return true; + } - // get version and unlock time from json - tx.version = j["version"].get(); - tx.unlock_time = j["unlock_time"].get(); + return false; +} - // next get extra data - for (json& extra_val: j["extra"]) - tx.extra.push_back(extra_val.get()); +bool +get_real_output_for_key_image(const key_image& ki, + const transaction& tx, + const secret_key& private_view_key, + const public_key& public_spend_key, + uint64_t output_idx, + public_key output_pub_key) +{ - // now populate output data from json - vector& tx_outputs = tx.vout; - for (json& vo: j["vout"]) - { - uint64_t amount = vo["amount"].get(); - public_key out_pub_key; - - if (!epee::string_tools::hex_to_pod(vo["target"]["key"], out_pub_key)) - { - cerr << "Faild to parse public_key of an output from json" << endl; - return false; - } + return false; +} - txout_target_v target {txout_to_key {out_pub_key}}; - tx_outputs.push_back(tx_out {amount, target}); - } +string +make_printable(const string& in_s) +{ + string output; - // now populate input data from json - vector& tx_inputs = tx.vin; + for (char c: in_s) + { - for (json& vi: j["vin"]) + if (isprint(c)) { - uint64_t amount = vi["key"]["amount"].get(); - - key_image in_key_image; - - if (!epee::string_tools::hex_to_pod(vi["key"]["k_image"], in_key_image)) - { - cerr << "Faild to parse key_image of an input from json" << endl; - return false; - } - - vector key_offsets; - - for (json& ko: vi["key"]["key_offsets"]) - { - key_offsets.push_back(ko.get()); - } - - txin_v _txin_v {txin_to_key {amount, key_offsets, in_key_image}}; - - tx_inputs.push_back(_txin_v); + output += c; } - - // add ring signatures field - - if (j.find("signatures") != j.end()) + else { - vector>& signatures = tx.signatures; - - for (json& sigs: j["signatures"]) - { - string concatanted_sig = sigs; - - vector sig_split; - - auto split_sig = [&](string::iterator &b, string::iterator &e) - { - signature a_sig; - - if (!epee::string_tools::hex_to_pod(string(b, e), a_sig)) - { - cerr << "Faild to parse signature from json" << endl; - return false; - } - - sig_split.push_back(a_sig); - - return true; - }; - - chunks(concatanted_sig.begin(), concatanted_sig.end(), 128, split_sig); - - signatures.push_back(sig_split); + switch(c){ + case '\000': output += "\\000";break; + case '\001': output += "\\001";break; + case '\002': output += "\\002";break; + case '\003': output += "\\003";break; + case '\004': output += "\\004";break; + case '\005': output += "\\005";break; + case '\006': output += "\\006";break; + case '\007': output += "\\007";break; + // there are more case but for now its ok + default: + stringstream ss; + ss << std::hex << (int)c; + output += "0x" + ss.str(); + break; } - } - // now add rct_signatures from json to tx if exist - - if (j.find("rct_signatures") != j.end()) - { - rct::rctSig& rct_signatures = tx.rct_signatures; - - if (j["rct_signatures"].find("pseudoOuts") != j["rct_signatures"].end()) - { - rct::keyV& pseudoOuts = rct_signatures.pseudoOuts; - - for (json& pOut: j["rct_signatures"]["pseudoOuts"]) - { - rct::key pOut_key; - - if (!epee::string_tools::hex_to_pod(pOut, pOut_key)) - { - cerr << "Faild to parse pOut_key of pseudoOuts from json" << endl; - return false; - } - - pseudoOuts.push_back(pOut_key); - } - } - - vector& ecdhInfo = rct_signatures.ecdhInfo; - - for (json& ecdhI: j["rct_signatures"]["ecdhInfo"]) - { - rct::ecdhTuple a_tuple; - - //cout << "ecdhI[\"amount\"]: " << ecdhI["amount"] << endl; - - if (!epee::string_tools::hex_to_pod(ecdhI["amount"], a_tuple.amount)) - { - cerr << "Faild to parse ecdhInfo of an amount from json" << endl; - return false; - } - - //cout << epee::string_tools::pod_to_hex(a_tuple.amount) << endl; - - if (!epee::string_tools::hex_to_pod(ecdhI["mask"], a_tuple.mask)) - { - cerr << "Faild to parse ecdhInfo of an mask from json" << endl; - return false; - } - - ecdhInfo.push_back(a_tuple); - } - - vector& outPk = rct_signatures.outPk; - - for (json& pk: j["rct_signatures"]["outPk"]) - { - outPk.push_back(rct::ctkey {rct::zero(), rct::zero()}); - - rct::key& mask = outPk.back().mask; - - if (!epee::string_tools::hex_to_pod(pk, mask)) - { - cerr << "Faild to parse rct::key of an outPk from json" << endl; - return false; - } - - // cout << "dest: " << epee::string_tools::pod_to_hex(outPk.back().mask) << endl; - } - - rct_signatures.txnFee = j["rct_signatures"]["txnFee"].get(); - rct_signatures.type = j["rct_signatures"]["type"].get(); - - } // if (j.find("rct_signatures") != j.end()) - - - if (j.find("rctsig_prunable") != j.end()) - { - rct::rctSigPrunable& rctsig_prunable = tx.rct_signatures.p; - - vector& range_sigs = rctsig_prunable.rangeSigs; - - for (json& range_s: j["rctsig_prunable"]["rangeSigs"]) - { - rct::boroSig asig; - - if (!epee::string_tools::hex_to_pod(range_s["asig"], asig)) - { - cerr << "Faild to parse asig of an asnlSig from json" << endl; - return false; - } - - - struct { - rct::key64 Ci; - } key64_contained; - - if (!epee::string_tools::hex_to_pod(range_s["Ci"], key64_contained)) - { - cerr << "Faild to parse Ci of an asnlSig from json" << endl; - return false; - } - - range_sigs.push_back(rct::rangeSig {}); - - rct::rangeSig& last_range_sig = range_sigs.back(); - - last_range_sig.asig = asig; - - memcpy(&(last_range_sig.Ci), &(key64_contained.Ci), sizeof(rct::key64)); - - } // for (json& range_s: j["rctsig_prunable"]["rangeSigs"]) - - vector& mg_sigs = rctsig_prunable.MGs; - - for (json& a_mgs: j["rctsig_prunable"]["MGs"]) - { - rct::mgSig new_mg_sig; - - vector& ss = new_mg_sig.ss; - - for (json& ss_j: a_mgs["ss"]) - { - rct::key a_key1; - - if (!epee::string_tools::hex_to_pod(ss_j[0], a_key1)) - { - cerr << "Faild to parse ss a_key1 of an MGs from json" << endl; - return false; - } - - rct::key a_key2; - - if (!epee::string_tools::hex_to_pod(ss_j[1], a_key2)) - { - cerr << "Faild to parse ss a_key2 of an MGs from json" << endl; - return false; - } - - ss.push_back(vector{a_key1, a_key2}); - } - - json& cc_j = a_mgs["cc"]; - - if (!epee::string_tools::hex_to_pod(cc_j, new_mg_sig.cc)) - { - cerr << "Faild to parse cc an MGs from json" << endl; - return false; - } - - mg_sigs.push_back(new_mg_sig); - } // for (json& a_mgs: j["rctsig_prunable"]["MGs"]) - - //std::vector& bulletproof = rctsig_prunable.bulletproofs; - - - - } // j.find("rctsig_prunable") != j.end() - - - - - //cout << "From reconstructed tx: " << obj_to_json_str(tx) << endl; - - return true; } + return output; +} - string - make_printable(const string& in_s) - { - string output; - - for (char c: in_s) - { - - if (isprint(c)) - { - output += c; - } - else - { - switch(c){ - case '\000': output += "\\000";break; - case '\001': output += "\\001";break; - case '\002': output += "\\002";break; - case '\003': output += "\\003";break; - case '\004': output += "\\004";break; - case '\005': output += "\\005";break; - case '\006': output += "\\006";break; - case '\007': output += "\\007";break; - // there are more case but for now its ok - default: - stringstream ss; - ss << std::hex << (int)c; - output += "0x" + ss.str(); - break; - } - } - - } - - return output; - } +string +get_human_readable_timestamp(uint64_t ts) +{ + char buffer[64]; + if (ts < 1234567890) + return ""; + time_t tt = ts; - string - get_human_readable_timestamp(uint64_t ts) - { - char buffer[64]; - if (ts < 1234567890) - return ""; + struct tm tm; - time_t tt = ts; + gmtime_r(&tt, &tm); - struct tm tm; + strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M:%S", &tm); - gmtime_r(&tt, &tm); + return std::string(buffer); +} - strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M:%S", &tm); +void +pause_execution(uint64_t no_seconds, const string& text) +{ - return std::string(buffer); - } + cout << "\nPausing " << text + << " for " << no_seconds << " seconds: " + << flush; - void - pause_execution(uint64_t no_seconds, const string& text) + for (size_t i = 0; i < no_seconds; ++i) { - - cout << "\nPausing " << text - << " for " << no_seconds << " seconds: " - << flush; - - for (size_t i = 0; i < no_seconds; ++i) - { - cout << "." << flush; - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - cout << endl; + cout << "." << flush; + std::this_thread::sleep_for(std::chrono::seconds(1)); } + cout << endl; +} + }