diff options
36 files changed, 445 insertions, 122 deletions
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index cb617bb9a..70782d9d3 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -88,7 +88,7 @@ static const char *get_default_categories(int level) switch (level) { case 0: - categories = "*:WARNING,net:FATAL,net.p2p:FATAL,global:INFO,verify:FATAL,stacktrace:INFO"; + categories = "*:WARNING,net:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO"; break; case 1: categories = "*:WARNING,global:INFO,stacktrace:INFO"; @@ -142,7 +142,7 @@ void mlog_configure(const std::string &filename_base, bool console) void mlog_set_categories(const char *categories) { el::Loggers::setCategories(categories); - MGINFO("New log categories: " << categories); + MDEBUG("New log categories: " << categories); } // maps epee style log level to new logging system @@ -150,7 +150,7 @@ void mlog_set_log_level(int level) { const char *categories = get_default_categories(level); el::Loggers::setCategories(categories); - MGINFO("New log categories: " << categories); + MDEBUG("New log categories: " << categories); } void mlog_set_log(const char *log) diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 39208250d..674b844c1 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -37,7 +37,7 @@ #include "cryptonote_protocol/blobdatatype.h" #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/difficulty.h" -#include "cryptonote_basic/hardfork.h" +#include "cryptonote_core/hardfork.h" /** \file * Cryptonote Blockchain Database Interface diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index 9df157a9e..db478c690 100644 --- a/src/cryptonote_basic/CMakeLists.txt +++ b/src/cryptonote_basic/CMakeLists.txt @@ -32,8 +32,7 @@ set(cryptonote_basic_sources cryptonote_basic_impl.cpp cryptonote_format_utils.cpp difficulty.cpp - miner.cpp - hardfork.cpp) + miner.cpp) set(cryptonote_basic_headers) @@ -50,8 +49,7 @@ set(cryptonote_basic_private_headers difficulty.h miner.h tx_extra.h - verification_context.h - hardfork.h) + verification_context.h) monero_private_headers(cryptonote_basic ${crypto_private_headers}) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index f933e9cac..ed2787cf7 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -250,6 +250,28 @@ namespace cryptonote } END_SERIALIZE() + template<bool W, template <bool> class Archive> + bool serialize_base(Archive<W> &ar) + { + FIELDS(*static_cast<transaction_prefix *>(this)) + + if (version == 1) + { + } + else + { + ar.tag("rct_signatures"); + if (!vin.empty()) + { + ar.begin_object(); + bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size()); + if (!r || !ar.stream().good()) return false; + ar.end_object(); + } + } + return true; + } + private: static size_t get_signature_size(const txin_v& tx_in); }; diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 89cd013ae..6baa57d26 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -93,6 +93,16 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx) + { + std::stringstream ss; + ss << tx_blob; + binary_archive<false> ba(ss); + bool r = tx.serialize_base(ba); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + return true; + } + //--------------------------------------------------------------- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) { std::stringstream ss; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index f8c70dc19..b527502ac 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -44,6 +44,7 @@ namespace cryptonote crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); + bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 5944ddcd1..8a72dd259 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -30,6 +30,7 @@ set(cryptonote_core_sources blockchain.cpp cryptonote_core.cpp tx_pool.cpp + hardfork.cpp cryptonote_tx_utils.cpp) set(cryptonote_core_headers) @@ -37,6 +38,7 @@ set(cryptonote_core_headers) set(cryptonote_core_private_headers blockchain_storage_boost_serialization.h blockchain.h + hardfork.h cryptonote_core.h tx_pool.h cryptonote_tx_utils.h) diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 2c7420e18..6e4ba5e2a 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -51,7 +51,7 @@ #include "cryptonote_basic/verification_context.h" #include "crypto/hash.h" #include "cryptonote_basic/checkpoints.h" -#include "cryptonote_basic/hardfork.h" +#include "cryptonote_core/hardfork.h" #include "blockchain_db/blockchain_db.h" namespace cryptonote diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_core/hardfork.cpp index 24d6655f0..50da70050 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_core/hardfork.cpp @@ -29,7 +29,7 @@ #include <algorithm> #include <cstdio> -#include "cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_basic.h" #include "blockchain_db/blockchain_db.h" #include "hardfork.h" diff --git a/src/cryptonote_basic/hardfork.h b/src/cryptonote_core/hardfork.h index 11241e657..6c6fbcb84 100644 --- a/src/cryptonote_basic/hardfork.h +++ b/src/cryptonote_core/hardfork.h @@ -29,7 +29,7 @@ #pragma once #include "syncobj.h" -#include "cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_basic.h" namespace cryptonote { diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index e06d9cd31..e31276031 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp @@ -122,7 +122,7 @@ cryptonote_protocol_handler_base::~cryptonote_protocol_handler_base() { void cryptonote_protocol_handler_base::handler_request_blocks_history(std::list<crypto::hash>& ids) { using namespace epee::net_utils; MDEBUG("### ~~~RRRR~~~~ ### sending request (type 2), limit = " << ids.size()); - MWARNING("RATE LIMIT NOT IMPLEMENTED HERE YET (download at unlimited speed?)"); + MDEBUG("RATE LIMIT NOT IMPLEMENTED HERE YET (download at unlimited speed?)"); // TODO } diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 8daaac611..4e6e83eb5 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -552,4 +552,15 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector return m_executor.print_blockchain_dynamic_stats(nblocks); } +bool t_command_parser_executor::update(const std::vector<std::string>& args) +{ + if(args.size() != 1) + { + std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl; + return false; + } + + return m_executor.update(args.front()); +} + } // namespace daemonize diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index 37f431974..0a5ca8dd9 100644 --- a/src/daemon/command_parser_executor.h +++ b/src/daemon/command_parser_executor.h @@ -130,6 +130,8 @@ public: bool alt_chain_info(const std::vector<std::string>& args); bool print_blockchain_dynamic_stats(const std::vector<std::string>& args); + + bool update(const std::vector<std::string>& args); }; } // namespace daemonize diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 4a063268f..0081e00dc 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -243,6 +243,11 @@ t_command_server::t_command_server( , std::bind(&t_command_parser_executor::print_blockchain_dynamic_stats, &m_parser, p::_1) , "Print information about current blockchain dynamic state" ); + m_command_lookup.set_handler( + "update" + , std::bind(&t_command_parser_executor::update, &m_parser, p::_1) + , "subcommands: check (check if an update is available), download (download it is there is), update (not implemented)" + ); } bool t_command_server::process_command_str(const std::string& cmd) diff --git a/src/daemon/protocol.h b/src/daemon/protocol.h index a59b6ab1e..fc5edbcaa 100644 --- a/src/daemon/protocol.h +++ b/src/daemon/protocol.h @@ -79,7 +79,6 @@ public: m_protocol.deinit(); m_protocol.set_p2p_endpoint(nullptr); MGINFO("Cryptonote protocol stopped successfully"); - tools::success_msg_writer() << "Daemon stopped successfully"; } catch (...) { LOG_ERROR("Failed to stop cryptonote protocol!"); } diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index b33736839..80109c791 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -34,7 +34,7 @@ #include "daemon/rpc_command_executor.h" #include "rpc/core_rpc_server_commands_defs.h" #include "cryptonote_core/cryptonote_core.h" -#include "cryptonote_basic/hardfork.h" +#include "cryptonote_core/hardfork.h" #include <boost/format.hpp> #include <ctime> #include <string> @@ -1494,7 +1494,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) { return true; } - if (!m_rpc_client->rpc_request(fereq, feres, "/get_fee_estimate", fail_message.c_str())) + if (!m_rpc_client->json_rpc_request(fereq, feres, "get_fee_estimate", fail_message.c_str())) { return true; } @@ -1525,7 +1525,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) bhreq.end_height = ires.height - 1; if (m_is_rpc) { - if (!m_rpc_client->rpc_request(bhreq, bhres, "/getblockheadersrange", fail_message.c_str())) + if (!m_rpc_client->json_rpc_request(bhreq, bhres, "getblockheadersrange", fail_message.c_str())) { return true; } @@ -1580,4 +1580,51 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) return true; } +bool t_rpc_command_executor::update(const std::string &command) +{ + cryptonote::COMMAND_RPC_UPDATE::request req; + cryptonote::COMMAND_RPC_UPDATE::response res; + epee::json_rpc::error error_resp; + + std::string fail_message = "Problem fetching info"; + + req.command = command; + if (m_is_rpc) + { + if (!m_rpc_client->rpc_request(req, res, "/update", fail_message.c_str())) + { + return true; + } + } + else + { + if (!m_rpc_server->on_update(req, res) || res.status != CORE_RPC_STATUS_OK) + { + tools::fail_msg_writer() << fail_message.c_str(); + return true; + } + } + + if (!res.update) + { + tools::msg_writer() << "No update available"; + return true; + } + + tools::msg_writer() << "Update available: v" << res.version << ": " << res.user_uri << ", hash " << res.hash; + if (command == "check") + return true; + + if (!res.path.empty()) + tools::msg_writer() << "Update downloaded to: " << res.path; + else + tools::msg_writer() << "Update download failed: " << res.status; + if (command == "download") + return true; + + tools::msg_writer() << "'update' not implemented yet"; + + return true; +} + }// namespace daemonize diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index eb95101ce..a015c83ea 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -151,6 +151,8 @@ public: bool alt_chain_info(); bool print_blockchain_dynamic_stats(uint64_t nblocks); + + bool update(const std::string &command); }; } // namespace daemonize diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index c40bd8c5d..99c4e9282 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1023,7 +1023,14 @@ namespace nodetool while(rand_count < (max_random_index+1)*3 && try_count < 10 && !m_net_server.is_stop_signal_sent()) { ++rand_count; - size_t random_index = get_random_index_with_fixed_probability(max_random_index); + size_t random_index; + + if (use_white_list) { + random_index = get_random_index_with_fixed_probability(max_random_index); + } else { + random_index = crypto::rand<size_t>() % m_peerlist.get_gray_peers_count(); + } + CHECK_AND_ASSERT_MES(random_index < local_peers_count, false, "random_starter_index < peers_local.size() failed!!"); if(tried_peers.count(random_index)) diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 6b999207b..11d995995 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -408,13 +408,10 @@ namespace nodetool return false; } - size_t x = crypto::rand<size_t>() % (m_peers_gray.size() + 1); - size_t res = (x * x * x) / (m_peers_gray.size() * m_peers_gray.size()); //parabola \/ - - LOG_PRINT_L3("Random gray peer index=" << res << "(x="<< x << ", max_index=" << m_peers_gray.size() << ")"); + size_t random_index = crypto::rand<size_t>() % m_peers_gray.size(); peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>(); - pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), res); + pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), random_index); return true; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f64e7dd41..8efd6a07c 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -873,8 +873,7 @@ namespace rct { // must know the destination private key to find the correct amount, else will return a random number xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig"); - CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); - CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); + CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); //mask amount and mask @@ -902,8 +901,7 @@ namespace rct { xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig"); - CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); - CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); + CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); //mask amount and mask diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d79621de4..b114f77ae 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -33,6 +33,9 @@ using namespace epee; #include "core_rpc_server.h" #include "common/command_line.h" +#include "common/updates.h" +#include "common/download.h" +#include "common/util.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_basic/account.h" #include "cryptonote_basic/cryptonote_basic_impl.h" @@ -41,6 +44,9 @@ using namespace epee; #include "rpc/rpc_args.h" #include "core_rpc_server_error_codes.h" +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc" + #define MAX_RESTRICTED_FAKE_OUTS_COUNT 40 #define MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT 500 @@ -148,6 +154,23 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobdata) + { + cryptonote::transaction tx; + + if (!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx)) + { + MERROR("Failed to parse and validate tx from blob"); + return blobdata; + } + + std::stringstream ss; + binary_archive<true> ba(ss); + bool r = tx.serialize_base(ba); + CHECK_AND_ASSERT_MES(r, blobdata, "Failed to serialize rct signatures base"); + return ss.str(); + } + //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res) { CHECK_CORE_BUSY(); @@ -159,10 +182,13 @@ namespace cryptonote return false; } + size_t pruned_size = 0, unpruned_size = 0, ntxes = 0; for(auto& bd: bs) { res.blocks.resize(res.blocks.size()+1); res.blocks.back().block = bd.first; + pruned_size += bd.first.size(); + unpruned_size += bd.first.size(); res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices()); res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); block b; @@ -178,9 +204,15 @@ namespace cryptonote return false; } size_t txidx = 0; + ntxes += bd.second.size(); for(const auto& t: bd.second) { - res.blocks.back().txs.push_back(t); + if (req.prune) + res.blocks.back().txs.push_back(get_pruned_tx_blob(t)); + else + res.blocks.back().txs.push_back(t); + pruned_size += res.blocks.back().txs.back().size(); + unpruned_size += t.size(); res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); bool r = m_core.get_tx_outputs_gindexs(b.tx_hashes[txidx++], res.output_indices.back().indices.back().indices); if (!r) @@ -191,6 +223,7 @@ namespace cryptonote } } + MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, pruned size " << pruned_size << ", unpruned size " << unpruned_size); res.status = CORE_RPC_STATUS_OK; return true; } @@ -1455,6 +1488,98 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res) + { + static const char software[] = "monero"; +#ifdef BUILDTAG + static const char buildtag[] = BOOST_PP_STRINGIZE(BUILDTAG); +#else + static const char buildtag[] = "source"; +#endif + + if (req.command != "check" && req.command != "download" && req.command != "update") + { + res.status = std::string("unknown command: '") + req.command + "'"; + return true; + } + + std::string version, hash; + if (!tools::check_updates(software, buildtag, version, hash)) + { + res.status = "Error checking for updates"; + return true; + } + if (tools::vercmp(version.c_str(), MONERO_VERSION) <= 0) + { + res.update = false; + res.status = CORE_RPC_STATUS_OK; + return true; + } + res.update = true; + res.version = version; + res.user_uri = tools::get_update_url(software, "cli", buildtag, version, true); + res.auto_uri = tools::get_update_url(software, "cli", buildtag, version, false); + res.hash = hash; + if (req.command == "check") + { + res.status = CORE_RPC_STATUS_OK; + return true; + } + + boost::filesystem::path path; + if (req.path.empty()) + { + std::string filename; + const char *slash = strrchr(res.auto_uri.c_str(), '/'); + if (slash) + filename = slash + 1; + else + filename = std::string(software) + "-update-" + version; + path = epee::string_tools::get_current_module_folder(); + path /= filename; + } + else + { + path = req.path; + } + + crypto::hash file_hash; + if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash))) + { + MDEBUG("We don't have that file already, downloading"); + if (!tools::download(path.string(), res.auto_uri)) + { + MERROR("Failed to download " << res.auto_uri); + return false; + } + if (!tools::sha256sum(path.string(), file_hash)) + { + MERROR("Failed to hash " << path); + return false; + } + if (hash != epee::string_tools::pod_to_hex(file_hash)) + { + MERROR("Download from " << res.auto_uri << " does not match the expected hash"); + return false; + } + MINFO("New version downloaded to " << path); + } + else + { + MDEBUG("We already have " << path << " with expected hash"); + } + res.path = path.string(); + + if (req.command == "download") + { + res.status = CORE_RPC_STATUS_OK; + return true; + } + + res.status = "'update' not implemented yet"; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_bind_port = { "rpc-bind-port" diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 00db47c2d..900f473a9 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -98,6 +98,7 @@ namespace cryptonote MAP_URI_AUTO_JON2_IF("/start_save_graph", on_start_save_graph, COMMAND_RPC_START_SAVE_GRAPH, !m_restricted) MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted) MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS) + MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted) BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH) @@ -148,6 +149,7 @@ namespace cryptonote bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res); bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res); bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res); + bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res); //json_rpc bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 9f15da82a..99aa9815e 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 1 -#define CORE_RPC_VERSION_MINOR 6 +#define CORE_RPC_VERSION_MINOR 7 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -80,9 +80,11 @@ namespace cryptonote { std::list<crypto::hash> block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ uint64_t start_height; + bool prune; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) KV_SERIALIZE(start_height) + KV_SERIALIZE(prune) END_KV_SERIALIZE_MAP() }; @@ -1438,4 +1440,39 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; }; + + struct COMMAND_RPC_UPDATE + { + struct request + { + std::string command; + std::string path; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(command); + KV_SERIALIZE(path); + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string status; + bool update; + std::string version; + std::string user_uri; + std::string auto_uri; + std::string hash; + std::string path; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(status) + KV_SERIALIZE(update) + KV_SERIALIZE(version) + KV_SERIALIZE(user_uri) + KV_SERIALIZE(auto_uri) + KV_SERIALIZE(hash) + KV_SERIALIZE(path) + END_KV_SERIALIZE_MAP() + }; + }; } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 77681ada0..3a1f251d1 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1638,11 +1638,11 @@ void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block m_refresh_progress_reporter.update(height, false); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) +void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) { message_writer(console_color_green, false) << "\r" << tr("Height ") << height << ", " << - tr("transaction ") << get_transaction_hash(tx) << ", " << + tr("transaction ") << txid << ", " << tr("received ") << print_money(amount); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); @@ -1650,16 +1650,16 @@ void simple_wallet::on_money_received(uint64_t height, const cryptonote::transac m_refresh_progress_reporter.update(height, true); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) +void simple_wallet::on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) { // Not implemented in CLI wallet } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) +void simple_wallet::on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) { message_writer(console_color_magenta, false) << "\r" << tr("Height ") << height << ", " << - tr("transaction ") << get_transaction_hash(spend_tx) << ", " << + tr("transaction ") << txid << ", " << tr("spent ") << print_money(amount); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); @@ -1667,11 +1667,11 @@ void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transactio m_refresh_progress_reporter.update(height, true); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_skip_transaction(uint64_t height, const cryptonote::transaction& tx) +void simple_wallet::on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) { message_writer(console_color_red, true) << "\r" << tr("Height ") << height << ", " << - tr("transaction ") << get_transaction_hash(tx) << ", " << + tr("transaction ") << txid << ", " << tr("unsupported transaction format"); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); @@ -4333,7 +4333,8 @@ int main(int argc, char* argv[]) argc, argv, "monero-wallet-cli [--wallet-file=<file>|--generate-new-wallet=<file>] [<COMMAND>]", desc_params, - positional_options + positional_options, + "monero-wallet-cli.log" ); if (!vm) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index cd99757ab..2616cfd07 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -190,10 +190,10 @@ namespace cryptonote //----------------- i_wallet2_callback --------------------- virtual void on_new_block(uint64_t height, const cryptonote::block& block); - virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount); - virtual void on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount); - virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx); - virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx); + virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount); + virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount); + virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx); + virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx); //---------------------------------------------------------- friend class refresh_progress_reporter_t; diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c798d4d31..99645189a 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -656,9 +656,11 @@ string WalletImpl::keysFilename() const return m_wallet->get_keys_file(); } -bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) +bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password) { clearStatus(); + if(daemon_username != "") + m_daemon_login.emplace(daemon_username, daemon_password); return doInit(daemon_address, upper_transaction_size_limit); } @@ -1365,7 +1367,7 @@ bool WalletImpl::isNewWallet() const bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit) { - if (!m_wallet->init(daemon_address, boost::none, upper_transaction_size_limit)) + if (!m_wallet->init(daemon_address, m_daemon_login, upper_transaction_size_limit)) return false; // in case new wallet, this will force fast-refresh (pulling hashes instead of blocks) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 3501fa0ac..456110908 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -78,7 +78,7 @@ public: bool store(const std::string &path); std::string filename() const; std::string keysFilename() const; - bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0); + bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = ""); bool connectToDaemon(); ConnectionStatus connected() const; void setTrustedDaemon(bool arg); @@ -170,6 +170,7 @@ private: std::atomic<bool> m_rebuildWalletCache; // cache connection status to avoid unnecessary RPC calls mutable std::atomic<bool> m_is_connected; + boost::optional<epee::net_utils::http::login> m_daemon_login{}; }; diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index cc249b5cc..b5f5ef78e 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -45,8 +45,43 @@ NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_clien , m_dynamic_per_kb_fee_estimate(0) , m_dynamic_per_kb_fee_estimate_cached_height(0) , m_dynamic_per_kb_fee_estimate_grace_blocks(0) + , m_rpc_version(0) {} +void NodeRPCProxy::invalidate() +{ + m_height = 0; + m_height_time = 0; + for (size_t n = 0; n < 256; ++n) + m_earliest_height[n] = 0; + m_dynamic_per_kb_fee_estimate = 0; + m_dynamic_per_kb_fee_estimate_cached_height = 0; + m_dynamic_per_kb_fee_estimate_grace_blocks = 0; + m_rpc_version = 0; +} + +boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version) +{ + const time_t now = time(NULL); + if (m_rpc_version == 0) + { + epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t); + epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_VERSION::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); + req_t.jsonrpc = "2.0"; + req_t.id = epee::serialization::storage_entry(0); + req_t.method = "get_version"; + m_daemon_rpc_mutex.lock(); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); + m_daemon_rpc_mutex.unlock(); + CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status == CORE_RPC_STATUS_OK, resp_t.result.status, "Failed to get daemon RPC version"); + m_rpc_version = resp_t.result.version; + } + rpc_version = m_rpc_version; + return boost::optional<std::string>(); +} + boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) { const time_t now = time(NULL); diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index e2f42d541..02d1d8d93 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.h @@ -41,6 +41,9 @@ class NodeRPCProxy public: NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex); + void invalidate(); + + boost::optional<std::string> get_rpc_version(uint32_t &version); boost::optional<std::string> get_height(uint64_t &height); void set_height(uint64_t h); boost::optional<std::string> get_earliest_height(uint8_t version, uint64_t &earliest_height); @@ -56,6 +59,7 @@ private: uint64_t m_dynamic_per_kb_fee_estimate; uint64_t m_dynamic_per_kb_fee_estimate_cached_height; uint64_t m_dynamic_per_kb_fee_estimate_grace_blocks; + uint32_t m_rpc_version; }; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 354417876..3c9d2406a 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -633,28 +633,13 @@ bool wallet2::wallet_generate_key_image_helper(const cryptonote::account_keys& a return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::process_new_transaction(const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool) +void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool) { - class lazy_txid_getter - { - const cryptonote::transaction &tx; - crypto::hash lazy_txid; - bool computed; - public: - lazy_txid_getter(const transaction &tx): tx(tx), computed(false) {} - const crypto::hash &operator()() - { - if (!computed) - { - lazy_txid = cryptonote::get_transaction_hash(tx); - computed = true; - } - return lazy_txid; - } - } txid(tx); + // In this function, tx (probably) only contains the base information + // (that is, the prunable stuff may or may not be included) if (!miner_tx) - process_unconfirmed(tx, height); + process_unconfirmed(txid, tx, height); std::vector<size_t> outs; uint64_t tx_money_got_in_outs = 0; crypto::public_key tx_pub_key = null_pkey; @@ -663,7 +648,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s 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 - LOG_PRINT_L0("Transaction extra has unsupported format: " << txid()); + LOG_PRINT_L0("Transaction extra has unsupported format: " << txid); } // Don't try to extract tx public key if tx has no ouputs @@ -677,9 +662,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s { if (pk_index > 1) break; - LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid()); + LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid); if(0 != m_callback) - m_callback->on_skip_transaction(height, tx); + m_callback->on_skip_transaction(height, txid, tx); return; } @@ -879,7 +864,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_internal_output_index = o; td.m_global_output_index = o_indices[o]; td.m_tx = (const cryptonote::transaction_prefix&)tx; - td.m_txid = txid(); + td.m_txid = txid; td.m_key_image = ki[o]; td.m_key_image_known = !m_watch_only; td.m_amount = tx.vout[o].amount; @@ -903,9 +888,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s set_unspent(m_transfers.size()-1); m_key_images[td.m_key_image] = m_transfers.size()-1; m_pub_keys[in_ephemeral[o].pub] = m_transfers.size()-1; - LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid()); + LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); if (0 != m_callback) - m_callback->on_money_received(height, tx, td.m_amount); + m_callback->on_money_received(height, txid, tx, td.m_amount); } } else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount) @@ -930,7 +915,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_internal_output_index = o; td.m_global_output_index = o_indices[o]; td.m_tx = (const cryptonote::transaction_prefix&)tx; - td.m_txid = txid(); + td.m_txid = txid; td.m_amount = tx.vout[o].amount; td.m_pk_index = pk_index - 1; if (td.m_amount == 0) @@ -952,9 +937,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s THROW_WALLET_EXCEPTION_IF(td.get_public_key() != in_ephemeral[o].pub, error::wallet_internal_error, "Inconsistent public keys"); THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status"); - LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid()); + LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); if (0 != m_callback) - m_callback->on_money_received(height, tx, td.m_amount); + m_callback->on_money_received(height, txid, tx, td.m_amount); } } } @@ -982,17 +967,17 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s tx_money_spent_in_ins += amount; if (!pool) { - LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid()); + LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid); set_spent(it->second, height); if (0 != m_callback) - m_callback->on_money_spent(height, tx, amount, tx); + m_callback->on_money_spent(height, txid, tx, amount, tx); } } } if (tx_money_spent_in_ins > 0) { - process_outgoing(tx, height, ts, tx_money_spent_in_ins, tx_money_got_in_outs); + process_outgoing(txid, tx, height, ts, tx_money_spent_in_ins, tx_money_got_in_outs); } uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0; @@ -1038,7 +1023,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } payment_details payment; - payment.m_tx_hash = txid(); + payment.m_tx_hash = txid; payment.m_amount = received; payment.m_block_height = height; payment.m_unlock_time = tx.unlock_time; @@ -1046,7 +1031,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if (pool) { m_unconfirmed_payments.emplace(txid(), payment); if (0 != m_callback) - m_callback->on_unconfirmed_money_received(height, tx, payment.m_amount); + m_callback->on_unconfirmed_money_received(height, txid, tx, payment.m_amount); } else m_payments.emplace(payment_id, payment); @@ -1054,12 +1039,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } } //---------------------------------------------------------------------------------------------------- -void wallet2::process_unconfirmed(const cryptonote::transaction& tx, uint64_t height) +void wallet2::process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height) { if (m_unconfirmed_txs.empty()) return; - crypto::hash txid = get_transaction_hash(tx); auto unconf_it = m_unconfirmed_txs.find(txid); if(unconf_it != m_unconfirmed_txs.end()) { if (store_tx_info()) { @@ -1075,9 +1059,8 @@ void wallet2::process_unconfirmed(const cryptonote::transaction& tx, uint64_t he } } //---------------------------------------------------------------------------------------------------- -void wallet2::process_outgoing(const cryptonote::transaction &tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received) +void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received) { - crypto::hash txid = get_transaction_hash(tx); std::pair<std::unordered_map<crypto::hash, confirmed_transfer_details>::iterator, bool> entry = m_confirmed_txs.insert(std::make_pair(txid, confirmed_transfer_details())); // fill with the info we know, some info might already be there if (entry.second) @@ -1120,16 +1103,19 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry if(b.timestamp + 60*60*24 > m_account.get_createtime() && height >= m_refresh_from_block_height) { TIME_MEASURE_START(miner_tx_handle_time); - process_new_transaction(b.miner_tx, o_indices.indices[txidx++].indices, height, b.timestamp, true, false); + process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, o_indices.indices[txidx++].indices, height, b.timestamp, true, false); TIME_MEASURE_FINISH(miner_tx_handle_time); TIME_MEASURE_START(txs_handle_time); - for(auto& txblob: bche.txs) + THROW_WALLET_EXCEPTION_IF(bche.txs.size() != b.tx_hashes.size(), error::wallet_internal_error, "Wrong amount of transactions for block"); + size_t idx = 0; + for (const auto& txblob: bche.txs) { cryptonote::transaction tx; - bool r = parse_and_validate_tx_from_blob(txblob, tx); + bool r = parse_and_validate_tx_base_from_blob(txblob, tx); THROW_WALLET_EXCEPTION_IF(!r, error::tx_parse_error, txblob); - process_new_transaction(tx, o_indices.indices[txidx++].indices, height, b.timestamp, false, false); + process_new_transaction(b.tx_hashes[idx], tx, o_indices.indices[txidx++].indices, height, b.timestamp, false, false); + ++idx; } TIME_MEASURE_FINISH(txs_handle_time); LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms"); @@ -1185,6 +1171,34 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res); req.block_ids = short_chain_history; + uint32_t rpc_version; + boost::optional<std::string> result = m_node_rpc_proxy.get_rpc_version(rpc_version); + // no error + if (!!result) + { + // empty string -> not connection + THROW_WALLET_EXCEPTION_IF(result->empty(), tools::error::no_connection_to_daemon, "getversion"); + THROW_WALLET_EXCEPTION_IF(*result == CORE_RPC_STATUS_BUSY, tools::error::daemon_busy, "getversion"); + if (*result != CORE_RPC_STATUS_OK) + { + MDEBUG("Cannot determined daemon RPC version, not asking for pruned blocks"); + req.prune = false; // old daemon + } + } + else + { + if (rpc_version >= MAKE_CORE_RPC_VERSION(1, 7)) + { + MDEBUG("Daemon is recent enough, asking for pruned blocks"); + req.prune = true; + } + else + { + MDEBUG("Daemon is too old, not asking for pruned blocks"); + req.prune = false; + } + } + req.start_height = start_height; m_daemon_rpc_mutex.lock(); bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout); @@ -1497,7 +1511,7 @@ void wallet2::update_pool_state() { if (tx_hash == txid) { - process_new_transaction(tx, std::vector<uint64_t>(), 0, time(NULL), false, true); + process_new_transaction(txid, tx, std::vector<uint64_t>(), 0, time(NULL), false, true); } else { @@ -2286,6 +2300,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout) if(!m_http_client.is_connected()) { + m_node_rpc_proxy.invalidate(); if (!m_http_client.connect(std::chrono::milliseconds(timeout))) return false; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 701a0e0b7..67bd93a82 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -70,10 +70,10 @@ namespace tools { public: virtual void on_new_block(uint64_t height, const cryptonote::block& block) {} - virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) {} - virtual void on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) {} - virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) {} - virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx) {} + virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) {} + virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) {} + virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) {} + virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {} virtual ~i_wallet2_callback() {} }; @@ -585,7 +585,7 @@ namespace tools * \param password Password of wallet file */ bool load_keys(const std::string& keys_file_name, const std::string& password); - void process_new_transaction(const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool); + void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool); void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height, const cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices &o_indices); void detach_blockchain(uint64_t height); void get_short_chain_history(std::list<crypto::hash>& ids) const; @@ -598,8 +598,8 @@ namespace tools void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, const std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t& blocks_added); uint64_t select_transfers(uint64_t needed_money, std::vector<size_t> unused_transfers_indices, std::list<size_t>& selected_transfers, bool trusted_daemon); bool prepare_file_names(const std::string& file_path); - void process_unconfirmed(const cryptonote::transaction& tx, uint64_t height); - void process_outgoing(const cryptonote::transaction& tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received); + void process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height); + void process_outgoing(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received); void add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amount_in, const std::vector<cryptonote::tx_destination_entry> &dests, const crypto::hash &payment_id, uint64_t change_amount); void generate_genesis(cryptonote::block& b); void check_genesis(const crypto::hash& genesis_hash) const; //throws diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index eec4f8b8f..e32d23d9f 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -340,7 +340,7 @@ struct Wallet * \param upper_transaction_size_limit * \return - true on success */ - virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) = 0; + virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username = "", const std::string &daemon_password = "") = 0; /*! * \brief createWatchOnly - Creates a watch only wallet diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index d2cda8700..166ce57e7 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -73,6 +73,7 @@ namespace wallet_args const char* const usage, boost::program_options::options_description desc_params, const boost::program_options::positional_options_description& positional_options, + const char *default_log_name, bool log_to_console) { @@ -106,35 +107,9 @@ namespace wallet_args po::options_description desc_all; desc_all.add(desc_general).add(desc_params); po::variables_map vm; - std::string log_path; bool r = command_line::handle_error_helper(desc_all, [&]() { - po::store(command_line::parse_command_line(argc, argv, desc_general, true), vm); - - if (command_line::has_arg(vm, arg_log_file)) - log_path = command_line::get_arg(vm, arg_log_file); - else - log_path = mlog_get_default_log_path("monero-wallet-cli.log"); - mlog_configure(log_path, log_to_console); - if (command_line::has_arg(vm, arg_log_level)) - { - mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); - } - - if (command_line::get_arg(vm, command_line::arg_help)) - { - tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"; - tools::msg_writer() << wallet_args::tr("Usage:") << ' ' << usage; - tools::msg_writer() << desc_all; - return false; - } - else if (command_line::get_arg(vm, command_line::arg_version)) - { - tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"; - return false; - } - - auto parser = po::command_line_parser(argc, argv).options(desc_params).positional(positional_options); + auto parser = po::command_line_parser(argc, argv).options(desc_all).positional(positional_options); po::store(parser.run(), vm); po::notify(vm); return true; @@ -142,6 +117,30 @@ namespace wallet_args if (!r) return boost::none; + std::string log_path; + if (!vm["log-file"].defaulted()) + log_path = command_line::get_arg(vm, arg_log_file); + else + log_path = mlog_get_default_log_path(default_log_name); + mlog_configure(log_path, log_to_console); + if (!vm["log-level"].defaulted()) + { + mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); + } + + if (command_line::get_arg(vm, command_line::arg_help)) + { + tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"; + tools::msg_writer() << wallet_args::tr("Usage:") << ' ' << usage; + tools::msg_writer() << desc_all; + return boost::none; + } + else if (command_line::get_arg(vm, command_line::arg_version)) + { + tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"; + return boost::none; + } + if(command_line::has_arg(vm, arg_max_concurrency)) tools::set_max_concurrency(command_line::get_arg(vm, arg_max_concurrency)); diff --git a/src/wallet/wallet_args.h b/src/wallet/wallet_args.h index e3466509e..cf23ffded 100644 --- a/src/wallet/wallet_args.h +++ b/src/wallet/wallet_args.h @@ -50,5 +50,5 @@ namespace wallet_args const char* const usage, boost::program_options::options_description desc_params, const boost::program_options::positional_options_description& positional_options, - bool log_to_console = false); + const char *default_log_name, bool log_to_console = false); } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 28606ed73..be8e0057d 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1397,6 +1397,7 @@ int main(int argc, char** argv) { "monero-wallet-rpc [--wallet-file=<file>|--generate-from-json=<file>] [--rpc-bind-port=<port>]", desc_params, po::positional_options_description(), + "monero-wallet-rpc.log", true ); if (!vm) diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 08c4276c8..512216ded 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -33,7 +33,7 @@ #include "blockchain_db/lmdb/db_lmdb.h" #include "cryptonote_basic/cryptonote_format_utils.h" -#include "cryptonote_basic/hardfork.h" +#include "cryptonote_core/hardfork.h" using namespace cryptonote; |