diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/wallet2.cpp | 137 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 14 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 41 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.h | 3 |
4 files changed, 106 insertions, 89 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5ab1ff85e..81472687d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -846,6 +846,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_key_image = ki[o]; td.m_key_image_known = !m_watch_only; td.m_amount = tx.vout[o].amount; + td.m_pk_index = pk_index - 1; if (td.m_amount == 0) { td.m_mask = mask[o]; @@ -894,6 +895,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_tx = (const cryptonote::transaction_prefix&)tx; td.m_txid = txid(); td.m_amount = tx.vout[o].amount; + td.m_pk_index = pk_index - 1; if (td.m_amount == 0) { td.m_mask = mask[o]; @@ -1573,35 +1575,12 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re std::list<cryptonote::block_complete_entry> blocks; std::vector<COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> o_indices; - std::string daemon_height_err = ""; - uint64_t daemon_bc_height = get_daemon_blockchain_height(daemon_height_err); - if(daemon_height_err.size() > 0) { - throw std::runtime_error(daemon_height_err); - } - // pull the first set of blocks get_short_chain_history(short_chain_history); m_run.store(true, std::memory_order_relaxed); if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) { - - // even target_height can be zero if the daemon just started and hasn't gotten some sync - // data back from peers .. hmmm, what to do ... O.o (you can see him thinking) - // i'm going with infiniti loop until i get something bigger than zero or err ... moneromoo don't kill me - std::string daemon_target_err = ""; - uint64_t daemon_target_height = 0; - - while(daemon_target_height == 0) - { - daemon_target_height = get_daemon_blockchain_target_height(daemon_target_err); - if(daemon_target_err.size() > 0) { - daemon_target_height = get_approximate_blockchain_height(); // - x? - } - } - - if (m_refresh_from_block_height > daemon_target_height) m_refresh_from_block_height = daemon_target_height - 1; - if (!start_height) start_height = m_refresh_from_block_height; - if (start_height >= daemon_bc_height) start_height = daemon_bc_height - 1; - + if (!start_height) + start_height = m_refresh_from_block_height; // we can shortcut by only pulling hashes up to the start_height fast_refresh(start_height, blocks_start_height, short_chain_history); // regenerate the history now that we've got a full set of hashes @@ -1611,56 +1590,53 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re // and then fall through to regular refresh processing } - if(!(m_refresh_from_block_height >= daemon_bc_height)) - { - pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices); - // always reset start_height to 0 to force short_chain_ history to be used on - // subsequent pulls in this refresh. - start_height = 0; + pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices); + // always reset start_height to 0 to force short_chain_ history to be used on + // subsequent pulls in this refresh. + start_height = 0; - while(m_run.load(std::memory_order_relaxed)) + while(m_run.load(std::memory_order_relaxed)) + { + try { - try - { - // pull the next set of blocks while we're processing the current one - uint64_t next_blocks_start_height; - std::list<cryptonote::block_complete_entry> next_blocks; - std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> next_o_indices; - bool error = false; - pull_thread = boost::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, next_o_indices, error);}); - - process_blocks(blocks_start_height, blocks, o_indices, added_blocks); - blocks_fetched += added_blocks; - pull_thread.join(); - if(!added_blocks) - break; + // pull the next set of blocks while we're processing the current one + uint64_t next_blocks_start_height; + std::list<cryptonote::block_complete_entry> next_blocks; + std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> next_o_indices; + bool error = false; + pull_thread = boost::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, next_o_indices, error);}); + + process_blocks(blocks_start_height, blocks, o_indices, added_blocks); + blocks_fetched += added_blocks; + pull_thread.join(); + if(!added_blocks) + break; - // switch to the new blocks from the daemon - blocks_start_height = next_blocks_start_height; - blocks = next_blocks; - o_indices = next_o_indices; + // switch to the new blocks from the daemon + blocks_start_height = next_blocks_start_height; + blocks = next_blocks; + o_indices = next_o_indices; - // handle error from async fetching thread - if (error) - { - throw std::runtime_error("proxy exception in refresh thread"); - } + // handle error from async fetching thread + if (error) + { + throw std::runtime_error("proxy exception in refresh thread"); } - catch (const std::exception&) + } + catch (const std::exception&) + { + blocks_fetched += added_blocks; + if (pull_thread.joinable()) + pull_thread.join(); + if(try_count < 3) { - blocks_fetched += added_blocks; - if (pull_thread.joinable()) - pull_thread.join(); - if(try_count < 3) - { - LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")..."); - ++try_count; - } - else - { - LOG_ERROR("pull_blocks failed, try_count=" << try_count); - throw; - } + LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")..."); + ++try_count; + } + else + { + LOG_ERROR("pull_blocks failed, try_count=" << try_count); + throw; } } } @@ -3623,7 +3599,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent real_oe.second.dest = rct::pk2rct(boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key); real_oe.second.mask = rct::commit(td.amount(), td.m_mask); *it_to_replace = real_oe; - src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx); + src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index); src.real_output = it_to_replace - src.outputs.begin(); src.real_output_in_tx_index = td.m_internal_output_index; detail::print_source_entry(src); @@ -3699,6 +3675,9 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); uint64_t needed_money = fee; LOG_PRINT_L2("transfer: starting with fee " << print_money (needed_money)); + LOG_PRINT_L0("selected transfers: "); + for (auto t: selected_transfers) + LOG_PRINT_L2(" " << t); // calculate total amount being sent to all destinations // throw if total amount overflows uint64_t @@ -3759,7 +3738,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry real_oe.second.dest = rct::pk2rct(boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key); real_oe.second.mask = rct::commit(td.amount(), td.m_mask); *it_to_replace = real_oe; - src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx); + src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index); src.real_output = it_to_replace - src.outputs.begin(); src.real_output_in_tx_index = td.m_internal_output_index; src.mask = td.m_mask; @@ -3770,12 +3749,22 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry // we still keep a copy, since we want to keep dsts free of change for user feedback purposes std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts; cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts); - if (needed_money < found_money) + change_dts.amount = found_money - needed_money; + if (change_dts.amount == 0) + { + // If the change is 0, send it to a random address, to avoid confusing + // the sender with a 0 amount output. We send a 0 amount in order to avoid + // letting the destination be able to work out which of the inputs is the + // real one in our rings + cryptonote::account_base dummy; + dummy.generate(); + change_dts.addr = dummy.get_keys().m_account_address; + } + else { change_dts.addr = m_account.get_keys().m_account_address; - change_dts.amount = found_money - needed_money; - splitted_dsts.push_back(change_dts); } + splitted_dsts.push_back(change_dts); crypto::secret_key tx_key; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, true); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index dcb6367d1..616b74edb 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -129,6 +129,7 @@ namespace tools uint64_t m_amount; bool m_rct; bool m_key_image_known; + size_t m_pk_index; bool is_rct() const { return m_rct; } uint64_t amount() const { return m_amount; } @@ -147,6 +148,7 @@ namespace tools FIELD(m_amount) FIELD(m_rct) FIELD(m_key_image_known) + FIELD(m_pk_index) END_SERIALIZE() }; @@ -644,7 +646,7 @@ namespace tools }; } BOOST_CLASS_VERSION(tools::wallet2, 15) -BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 6) +BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 7) BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1) BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6) BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 3) @@ -677,6 +679,10 @@ namespace boost { x.m_key_image_known = true; } + if (ver < 7) + { + x.m_pk_index = 0; + } } template <class Archive> @@ -738,6 +744,12 @@ namespace boost return; } a & x.m_key_image_known; + if (ver < 7) + { + initialize_transfer_details(a, x, ver); + return; + } + a & x.m_pk_index; } template <class Archive> diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5352b0b73..7c08bbe4b 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include <boost/asio/ip/address.hpp> #include <cstdint> #include "include_base_utils.h" using namespace epee; @@ -47,6 +48,8 @@ namespace const command_line::arg_descriptor<std::string, true> arg_rpc_bind_port = {"rpc-bind-port", "Sets bind port for server"}; const command_line::arg_descriptor<std::string> arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"}; const command_line::arg_descriptor<std::string> arg_user_agent = {"user-agent", "Restrict RPC to clients using this user agent", ""}; + + const command_line::arg_descriptor<bool> arg_confirm_external_bind = {"confirm-external-bind", "Confirm rcp-bind-ip value is NOT a loopback (local) IP"}; } namespace tools @@ -84,20 +87,35 @@ namespace tools return epee::http_server_impl_base<wallet_rpc_server, connection_context>::run(1, true); } //------------------------------------------------------------------------------------------------------------------------------ - bool wallet_rpc_server::handle_command_line(const boost::program_options::variables_map& vm) - { - m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip); - m_port = command_line::get_arg(vm, arg_rpc_bind_port); - m_user_agent = command_line::get_arg(vm, arg_user_agent); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::init(const boost::program_options::variables_map& vm) { + std::string bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip); + if (!bind_ip.empty()) + { + // always parse IP here for error consistency + boost::system::error_code ec{}; + const auto parsed_ip = boost::asio::ip::address::from_string(bind_ip, ec); + if (ec) + { + LOG_ERROR(tr("Invalid IP address given for rpc-bind-ip argument")); + return false; + } + + if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg_confirm_external_bind)) + { + LOG_ERROR( + tr("The rpc-bind-ip value is listening for unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --confirm-external-bind") + ); + return false; + } + } + m_net_server.set_threads_prefix("RPC"); - bool r = handle_command_line(vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server"); - return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(m_port, m_bind_ip, m_user_agent); + return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( + command_line::get_arg(vm, arg_rpc_bind_port), + std::move(bind_ip), + command_line::get_arg(vm, arg_user_agent) + ); } //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er) @@ -1115,6 +1133,7 @@ int main(int argc, char** argv) { command_line::add_arg(desc_params, arg_rpc_bind_ip); command_line::add_arg(desc_params, arg_rpc_bind_port); command_line::add_arg(desc_params, arg_user_agent); + command_line::add_arg(desc_params, arg_confirm_external_bind); command_line::add_arg(desc_params, arg_wallet_file); command_line::add_arg(desc_params, arg_from_json); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 7d6f94e56..96ca1af04 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -118,9 +118,6 @@ namespace tools bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er); wallet2& m_wallet; - std::string m_port; - std::string m_bind_ip; - std::string m_user_agent; std::atomic<bool> m_stop; }; } |