From 84066c7203111617fe742ff8f4310f1c4826cf0d Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 25 May 2023 20:05:39 +0200 Subject: [PATCH] added more proper handling of exception in rpc handlers --- src/simplewallet/simplewallet.cpp | 238 ++++++++++++++++-------------- src/wallet/wallet_rpc_server.cpp | 7 +- src/wallet/wallets_manager.cpp | 2 +- 3 files changed, 134 insertions(+), 113 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index fa6a42ed..7b9db781 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -41,6 +41,86 @@ namespace ph = boost::placeholders; #define EXTENDED_LOGS_FILE "wallet_details.log" +#define SIMPLE_WALLET_BEGIN_TRY_ENTRY() try { +#define SIMPLE_WALLET_CATCH_TRY_ENTRY() } \ + catch (const tools::error::daemon_busy&) \ + { \ + fail_msg_writer() << "daemon is busy. Please try later"; \ + } \ + catch (const tools::error::no_connection_to_daemon&) \ + { \ + fail_msg_writer() << "no connection to daemon. Please, make sure daemon is running."; \ + } \ + catch (const tools::error::wallet_rpc_error& e) \ + { \ + LOG_ERROR("Unknown RPC error: " << e.to_string()); \ + fail_msg_writer() << "RPC error \"" << e.what() << '"'; \ + } \ + catch (const tools::error::get_random_outs_error&) \ + { \ + fail_msg_writer() << "failed to get random outputs to mix"; \ + } \ + catch (const tools::error::not_enough_money& e) \ + { \ + fail_msg_writer() << "not enough money to transfer, available only " << print_money(e.available()) << \ + ", transaction amount " << print_money(e.tx_amount() + e.fee()) << " = " << print_money(e.tx_amount()) << \ + " + " << print_money(e.fee()) << " (fee)"; \ + } \ + catch (const tools::error::not_enough_outs_to_mix& e) \ + { \ + auto writer = fail_msg_writer(); \ + writer << "not enough outputs for specified mixin_count = " << e.mixin_count() << ":"; \ + for (const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs()) \ + { \ + writer << "\noutput amount = " << print_money(outs_for_amount.amount) << ", fount outputs to mix = " << outs_for_amount.outs.size(); \ + } \ + } \ + catch (const tools::error::tx_not_constructed&) \ + { \ + fail_msg_writer() << "transaction was not constructed"; \ + } \ + catch (const tools::error::tx_rejected& e) \ + { \ + fail_msg_writer() << "transaction " << get_transaction_hash(e.tx()) << " was rejected by daemon with status \"" << e.status() << '"'; \ + } \ + catch (const tools::error::tx_sum_overflow& e) \ + { \ + fail_msg_writer() << e.what(); \ + } \ + catch (const tools::error::tx_too_big& e) \ + { \ + currency::transaction tx = e.tx(); \ + fail_msg_writer() << "transaction " << get_transaction_hash(e.tx()) << " is too big. Transaction size: " << \ + get_object_blobsize(e.tx()) << " bytes, transaction size limit: " << e.tx_size_limit() << " bytes. Try to separate this payment into few smaller transfers."; \ + } \ + catch (const tools::error::zero_destination&) \ + { \ + fail_msg_writer() << "one of destinations is zero"; \ + } \ + catch (const tools::error::transfer_error& e) \ + { \ + LOG_ERROR("unknown transfer error: " << e.to_string()); \ + fail_msg_writer() << "unknown transfer error: " << e.what(); \ + } \ + catch (const tools::error::wallet_internal_error& e) \ + { \ + LOG_ERROR("internal error: " << e.to_string()); \ + fail_msg_writer() << "internal error: " << e.what(); \ + } \ + catch (const std::exception& e) \ + { \ + LOG_ERROR("unexpected error: " << e.what()); \ + fail_msg_writer() << "unexpected error: " << e.what(); \ + } \ + catch (...) \ + { \ + LOG_ERROR("Unknown error"); \ + fail_msg_writer() << "unknown error"; \ + } \ + + + + namespace { const command_line::arg_descriptor arg_wallet_file ("wallet-file", "Use wallet ", ""); @@ -1271,6 +1351,7 @@ bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id) //---------------------------------------------------------------------------------------------------- bool simple_wallet::transfer(const std::vector &args_) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!try_connect_to_daemon()) return true; @@ -1389,97 +1470,21 @@ bool simple_wallet::transfer(const std::vector &args_) return true; } - try - { - currency::transaction tx; - m_wallet->transfer(dsts, fake_outs_count, 0, m_wallet->get_core_runtime_config().tx_default_fee, extra, attachments, tx); + currency::transaction tx; + m_wallet->transfer(dsts, fake_outs_count, 0, m_wallet->get_core_runtime_config().tx_default_fee, extra, attachments, tx); - if (!m_wallet->is_watch_only()) - { - if(wrapped_transaction) - success_msg_writer(true) << "Money successfully sent to wZano custody wallet, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes"; - else - success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes"; - } + if (!m_wallet->is_watch_only()) + { + if(wrapped_transaction) + success_msg_writer(true) << "Money successfully sent to wZano custody wallet, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes"; else - { - success_msg_writer(true) << "Transaction prepared for signing and saved into \"zano_tx_unsigned\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network"; - } + success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes"; } - catch (const tools::error::daemon_busy&) + else { - fail_msg_writer() << "daemon is busy. Please try later"; - } - catch (const tools::error::no_connection_to_daemon&) - { - fail_msg_writer() << "no connection to daemon. Please, make sure daemon is running."; - } - catch (const tools::error::wallet_rpc_error& e) - { - LOG_ERROR("Unknown RPC error: " << e.to_string()); - fail_msg_writer() << "RPC error \"" << e.what() << '"'; - } - catch (const tools::error::get_random_outs_error&) - { - fail_msg_writer() << "failed to get random outputs to mix"; - } - catch (const tools::error::not_enough_money& e) - { - fail_msg_writer() << "not enough money to transfer, available only " << print_money(e.available()) << - ", transaction amount " << print_money(e.tx_amount() + e.fee()) << " = " << print_money(e.tx_amount()) << - " + " << print_money(e.fee()) << " (fee)"; - } - catch (const tools::error::not_enough_outs_to_mix& e) - { - auto writer = fail_msg_writer(); - writer << "not enough outputs for specified mixin_count = " << e.mixin_count() << ":"; - for (const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs()) - { - writer << "\noutput amount = " << print_money(outs_for_amount.amount) << ", fount outputs to mix = " << outs_for_amount.outs.size(); - } - } - catch (const tools::error::tx_not_constructed&) - { - fail_msg_writer() << "transaction was not constructed"; - } - catch (const tools::error::tx_rejected& e) - { - fail_msg_writer() << "transaction " << get_transaction_hash(e.tx()) << " was rejected by daemon with status \"" << e.status() << '"'; - } - catch (const tools::error::tx_sum_overflow& e) - { - fail_msg_writer() << e.what(); - } - catch (const tools::error::tx_too_big& e) - { - currency::transaction tx = e.tx(); - fail_msg_writer() << "transaction " << get_transaction_hash(e.tx()) << " is too big. Transaction size: " << - get_object_blobsize(e.tx()) << " bytes, transaction size limit: " << e.tx_size_limit() << " bytes. Try to separate this payment into few smaller transfers."; - } - catch (const tools::error::zero_destination&) - { - fail_msg_writer() << "one of destinations is zero"; - } - catch (const tools::error::transfer_error& e) - { - LOG_ERROR("unknown transfer error: " << e.to_string()); - fail_msg_writer() << "unknown transfer error: " << e.what(); - } - catch (const tools::error::wallet_internal_error& e) - { - LOG_ERROR("internal error: " << e.to_string()); - fail_msg_writer() << "internal error: " << e.what(); - } - catch (const std::exception& e) - { - LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << "unexpected error: " << e.what(); - } - catch (...) - { - LOG_ERROR("Unknown error"); - fail_msg_writer() << "unknown error"; - } + success_msg_writer(true) << "Transaction prepared for signing and saved into \"zano_tx_unsigned\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network"; + } + SIMPLE_WALLET_CATCH_TRY_ENTRY() return true; } @@ -1806,6 +1811,7 @@ bool simple_wallet::tor_disable(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::deploy_new_asset(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); asset_descriptor_base adb = AUTO_VAL_INIT(adb); if (!args.size() || args.size() > 1) { @@ -1826,19 +1832,21 @@ bool simple_wallet::deploy_new_asset(const std::vector &args) crypto::public_key result_asset_id = currency::null_pkey; m_wallet->publish_new_asset(adb, destinations, result_tx, result_asset_id); - success_msg_writer(true) << "New asset deployed: " << ENDL - << "Asset ID: " << result_asset_id << ENDL + success_msg_writer(true) << "New asset deployed: " << ENDL + << "Asset ID: " << result_asset_id << ENDL << "Title: " << adb.full_name << ENDL << "Ticker: " << adb.ticker << ENDL << "Emitted: " << print_fixed_decimal_point(adb.current_supply, adb.decimal_point) << ENDL << "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL ; - + + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::add_custom_asset_id(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!args.size() || args.size() > 1) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; @@ -1865,11 +1873,14 @@ bool simple_wallet::add_custom_asset_id(const std::vector &args) << " supply: " << print_fixed_decimal_point(asset_descriptor.current_supply, asset_descriptor.decimal_point) << ENDL ; } + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; + } //---------------------------------------------------------------------------------------------------- bool simple_wallet::generate_ionic_swap_proposal(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 2) { @@ -1906,11 +1917,15 @@ bool simple_wallet::generate_ionic_swap_proposal(const std::vector { success_msg_writer() << "Generated proposal: " << ENDL << epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(proposal)); } + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; + } //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_ionic_swap_proposal_info(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); + if (args.size() != 1) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; @@ -1935,11 +1950,14 @@ bool simple_wallet::get_ionic_swap_proposal_info(const std::vector success_msg_writer() << "Proposal details: " << ENDL << json_proposal_info; + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::accept_ionic_swap_proposal(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); + if (args.size() != 1) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; @@ -1962,12 +1980,14 @@ bool simple_wallet::accept_ionic_swap_proposal(const std::vector &a success_msg_writer() << "Proposal accepted and executed, tx_id : " << currency::get_transaction_hash(result_tx); + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::remove_custom_asset_id(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!args.size() || args.size() > 1) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; @@ -1989,11 +2009,14 @@ bool simple_wallet::remove_custom_asset_id(const std::vector &args) { success_msg_writer() << "Asset id " << asset_id << " removed from wallet custom list" << ENDL; } + + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector &args) { + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); bool r = false; if (args.size() < 3 || args.size() > 4) { @@ -2051,30 +2074,23 @@ bool simple_wallet::sweep_below(const std::vector &args) return true; } - try - { - uint64_t fee = m_wallet->get_core_runtime_config().tx_default_fee; - size_t outs_total = 0, outs_swept = 0; - uint64_t amount_total = 0, amount_swept = 0; - currency::transaction result_tx = AUTO_VAL_INIT(result_tx); - std::string filename = "zano_tx_unsigned"; - m_wallet->sweep_below(fake_outs_count, addr, amount, payment_id, fee, outs_total, amount_total, outs_swept, amount_swept, &result_tx, &filename); - success_msg_writer(false) << outs_swept << " outputs (" << print_money_brief(amount_swept) << " coins) of " << outs_total << " total (" << print_money_brief(amount_total) - << ") below the specified limit of " << print_money_brief(amount) << " were successfully swept"; + uint64_t fee = m_wallet->get_core_runtime_config().tx_default_fee; + size_t outs_total = 0, outs_swept = 0; + uint64_t amount_total = 0, amount_swept = 0; + currency::transaction result_tx = AUTO_VAL_INIT(result_tx); + std::string filename = "zano_tx_unsigned"; + m_wallet->sweep_below(fake_outs_count, addr, amount, payment_id, fee, outs_total, amount_total, outs_swept, amount_swept, &result_tx, &filename); - if (m_wallet->is_watch_only()) - success_msg_writer(true) << "Transaction prepared for signing and saved into \"" << filename << "\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network"; - else - success_msg_writer(true) << "tx: " << get_transaction_hash(result_tx) << " size: " << get_object_blobsize(result_tx) << " bytes"; - } - catch (const std::exception& e) - { - LOG_ERROR(e.what()); - fail_msg_writer() << e.what(); - return true; - } + success_msg_writer(false) << outs_swept << " outputs (" << print_money_brief(amount_swept) << " coins) of " << outs_total << " total (" << print_money_brief(amount_total) + << ") below the specified limit of " << print_money_brief(amount) << " were successfully swept"; + if (m_wallet->is_watch_only()) + success_msg_writer(true) << "Transaction prepared for signing and saved into \"" << filename << "\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network"; + else + success_msg_writer(true) << "tx: " << get_transaction_hash(result_tx) << " size: " << get_object_blobsize(result_tx) << " bytes"; + + SIMPLE_WALLET_CATCH_TRY_ENTRY(); return true; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 98a3a5ab..38c8146e 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -28,6 +28,12 @@ using namespace epee; er.message = e.error_code(); \ return false; \ } \ + catch (const tools::error::daemon_busy& e) \ + { \ + er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; \ + er.message = e.what(); \ + return false; \ + } \ catch (const std::exception& e) \ { \ er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; \ @@ -41,7 +47,6 @@ using namespace epee; return false; \ } - namespace tools { //----------------------------------------------------------------------------------- diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index c98ef0a2..48ce8eb3 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -2051,7 +2051,7 @@ bool wallets_manager::on_mw_select_wallet(uint64_t wallet_id) return false; m_rpc_selected_wallet_id = wallet_id; - return false; + return true; }