diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index e607044b..74bd96c6 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -274,6 +274,21 @@ namespace misc_utils } } + uint64_t get_avg() const + { + CRITICAL_REGION_LOCAL(m_lock); + if (!queued_items.size()) + return 0; + + uint64_t summ = 0; + for (const auto& item : queued_items) + { + summ += *item.first; + } + + return summ / queued_items.size(); + } + template friend std::ostream & operator<< (std::ostream &out, median_helper const &mh); }; // class median_helper diff --git a/src/common/error_codes.h b/src/common/error_codes.h index 0582e529..a1278d4b 100644 --- a/src/common/error_codes.h +++ b/src/common/error_codes.h @@ -24,6 +24,7 @@ #define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID" #define API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED "WALLET_WATCH_ONLY_NOT_SUPPORTED" #define API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED "WALLET_AUDITABLE_NOT_SUPPORTED" +#define API_RETURN_CODE_WALLET_FEE_TOO_LOW "API_RETURN_CODE_WALLET_FEE_TOO_LOW" #define API_RETURN_CODE_FILE_NOT_FOUND "FILE_NOT_FOUND" #define API_RETURN_CODE_ALREADY_EXISTS "ALREADY_EXISTS" #define API_RETURN_CODE_CANCELED "CANCELED" @@ -42,4 +43,4 @@ #define API_RETURN_CODE_TX_REJECTED "TX_REJECTED" #define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED" #define API_RETURN_CODE_WRAP "WRAP" -#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS" \ No newline at end of file +#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS" diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index c844b7b1..5c5f083b 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -4275,6 +4275,7 @@ uint64_t blockchain_storage::get_tx_fee_median() const //------------------------------------------------------------------ uint64_t blockchain_storage::get_alias_coast(const std::string& alias) const { + CRITICAL_REGION_LOCAL(m_read_lock); uint64_t median_fee = get_tx_fee_median(); //CHECK_AND_ASSERT_MES_NO_RET(median_fee, "can't calculate median"); @@ -4285,9 +4286,29 @@ uint64_t blockchain_storage::get_alias_coast(const std::string& alias) const return get_alias_coast_from_fee(alias, median_fee); } //------------------------------------------------------------------ +uint64_t blockchain_storage::get_tx_fee_window_value_median() const +{ + // calc it every time and cache it so it won't recalculated before next block + // it's effective because it's not affect sync time and needed only when node is synced + // and processing transactions + + misc_utils::median_helper mh; + for (uint64_t i = 0; i < CORE_FEE_BLOCKS_LOOKUP_WINDOW; i++) + { + uint64_t h = m_db_blocks.size() - 1 - i; + if (h >= m_db_blocks.size()) + break; + + auto block_ptr = m_db_blocks[h]; + CHECK_AND_ASSERT_THROW_MES(block_ptr, "Unexpected missing block " << h << " in get_tx_fee_window_value_median"); + mh.push_item(block_ptr->block_cumulative_size, 0); + } + + return (mh.get_median() + mh.get_avg())/2; +} +//------------------------------------------------------------------ bool blockchain_storage::unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp) { - size_t cnt_serv_attach = get_service_attachments_count_in_tx(tx); if (cnt_serv_attach == 0) return true; @@ -4599,7 +4620,7 @@ uint64_t blockchain_storage::tx_fee_median_for_height(uint64_t h)const //------------------------------------------------------------------ bool blockchain_storage::validate_all_aliases_for_new_median_mode() { - LOG_PRINT_L0("Started reinitialization of median fee..."); + LOG_PRINT_L0("Started reinitialization of median fee..."); math_helper::once_a_time_seconds<10> log_idle; uint64_t sz = m_db_blocks.size(); for (uint64_t i = 0; i != sz; i++) diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index ca11163c..cd1c0057 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -325,6 +325,7 @@ namespace currency boost::multiprecision::uint128_t total_coins()const; bool is_pos_allowed()const; uint64_t get_tx_fee_median()const; + uint64_t get_tx_fee_window_value_median() const; uint64_t get_tx_expiration_median() const; uint64_t validate_alias_reward(const transaction& tx, const std::string& ai)const; void set_event_handler(i_core_event_handler* event_handler) const; @@ -585,8 +586,8 @@ namespace currency mutable std::atomic m_deinit_is_done; mutable uint64_t m_blockchain_launch_timestamp; - bool init_tx_fee_median(); - bool update_tx_fee_median(); + //bool init_tx_fee_median(); + //bool update_tx_fee_median(); void store_db_solo_options_values(); bool set_lost_tx_unmixable(); bool set_lost_tx_unmixable_for_height(uint64_t height); @@ -653,6 +654,7 @@ namespace currency uint64_t get_tx_fee_median_effective_index(uint64_t h) const; void on_abort_transaction(); void load_targetdata_cache(bool is_pos) const; + uint64_t get_adjusted_time()const; diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index e291cc02..14070d4f 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -164,6 +164,8 @@ #define BLOCK_POS_STRICT_SEQUENCE_LIMIT 20 // the highest allowed sequence factor for a PoS block (i.e., the max total number of sequential PoS blocks is BLOCK_POS_STRICT_SEQUENCE_LIMIT + 1) +#define CORE_FEE_BLOCKS_LOOKUP_WINDOW 60 //number of blocks used to check if transaction flow is big enought to rise default fee + #define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare #define WALLET_FILE_SIGNATURE_V2 0x1111011201101011LL // another Bender's nightmare #define WALLET_FILE_BINARY_HEADER_VERSION_INITAL 1000 @@ -246,8 +248,8 @@ #define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin" #ifndef TESTNET -#define WALLET_FILE_SERIALIZATION_VERSION 160 -#define WALLET_FILE_LAST_SUPPORTED_VERSION 160 +#define WALLET_FILE_SERIALIZATION_VERSION 161 +#define WALLET_FILE_LAST_SUPPORTED_VERSION 161 #else #define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76) #define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 527dc76a..a77fb8a0 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -92,6 +92,15 @@ namespace currency return true; } //--------------------------------------------------------------------------------- + bool tx_memory_pool::check_tx_fee(const transaction &tx, uint64_t amount_fee) + { + if (amount_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee) + return false; + + //m_blockchain.get + return true; + } + //--------------------------------------------------------------------------------- bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core) { bool r = false; @@ -163,15 +172,15 @@ namespace currency CHECK_AND_ASSERT_MES(r, false, "Transaction " << id << " uses already spent key image " << spent_ki); //transaction spam protection, soft rule - if (tx_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee) + if (!check_tx_fee(tx, tx_fee)) { - if (is_valid_contract_finalization_tx(tx)) - { + //if (is_valid_contract_finalization_tx(tx)) + //{ // that means tx has less fee then allowed by current tx pull rules, but this transaction is actually // a finalization of contract, and template of this contract finalization tx was prepared actually before // fee rules had been changed, so it's ok, let it in. - } - else + //} + //else { // this tx has no fee LOG_PRINT_RED_L0("Transaction " << id << " has too small fee: " << print_money_brief(tx_fee) << ", minimum fee: " << print_money_brief(m_blockchain.get_core_runtime_config().tx_pool_min_fee)); diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index c9de4748..4ede52a2 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -145,6 +145,7 @@ namespace currency bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block); bool insert_alias_info(const transaction& tx); bool remove_alias_info(const transaction& tx); + bool check_tx_fee(const transaction &tx, uint64_t amount_fee); bool is_valid_contract_finalization_tx(const transaction &tx)const; void store_db_solo_options_values(); diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index 05f0bf55..3afb4e5a 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -1939,6 +1939,17 @@ QString MainWindow::restore_wallet(const QString& param) return MAKE_RESPONSE(ar); CATCH_ENTRY_FAIL_API_RESPONCE(); } +QString MainWindow::use_whitelisting(const QString& param) +{ + TRY_ENTRY(); + LOG_API_TIMING(); + //return que_call2("restore_wallet", param, [this](const view::restore_wallet_request& owd, view::api_response& ar){ + PREPARE_ARG_FROM_JSON(view::api_request_t, owd); + PREPARE_RESPONSE(view::api_responce_return_code, ar); + ar.error_code = m_backend.use_whitelisting(owd.wallet_id, owd.req_data); + return MAKE_RESPONSE(ar); + CATCH_ENTRY_FAIL_API_RESPONCE(); +} QString MainWindow::open_wallet(const QString& param) { TRY_ENTRY(); diff --git a/src/gui/qt-daemon/application/mainwindow.h b/src/gui/qt-daemon/application/mainwindow.h index f8dd6f27..ed980f7d 100644 --- a/src/gui/qt-daemon/application/mainwindow.h +++ b/src/gui/qt-daemon/application/mainwindow.h @@ -144,6 +144,7 @@ public: QString webkit_launched_script(); QString get_smart_wallet_info(const QString& param); QString restore_wallet(const QString& param); + QString use_whitelisting(const QString& param); QString is_pos_allowed(); QString store_to_file(const QString& path, const QString& buff); QString load_from_file(const QString& path); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4da5fb2a..f0dd80dd 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -116,7 +116,7 @@ namespace ph = boost::placeholders; fail_msg_writer() << "unknown error"; \ } \ - +#define CONFIRM_WITH_PASSWORD() if(!check_password_for_operation()) return true; namespace @@ -140,6 +140,7 @@ namespace const command_line::arg_descriptor arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false); const command_line::arg_descriptor arg_set_timeout("set-timeout", "Set timeout for the wallet"); const command_line::arg_descriptor arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", ""); + const command_line::arg_descriptor arg_no_password_confirmations("no-password-confirmation", "Enable/Disable password confirmation for transactions", false); const command_line::arg_descriptor< std::vector > arg_command ("command", ""); @@ -445,6 +446,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) m_do_refresh_after_load = false; } + m_password_salt = crypto::rand(); + m_password_hash = get_hash_from_pass_and_salt(pwd_container.password(), m_password_salt); + bool was_open = false; if (!m_generate_new.empty()) { @@ -516,6 +520,12 @@ bool simple_wallet::deinit() return close_wallet(); } //---------------------------------------------------------------------------------------------------- +crypto::hash simple_wallet::get_hash_from_pass_and_salt(const std::string& pass, uint64_t salt) +{ + std::string pass_and_salt = pass + std::to_string(salt); + return crypto::cn_fast_hash(pass_and_salt.data(), pass_and_salt.size()); +} +//---------------------------------------------------------------------------------------------------- void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm) { m_wallet_file = command_line::get_arg(vm, arg_wallet_file); @@ -529,8 +539,36 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_ m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet); m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay); m_voting_config_file = command_line::get_arg(vm, arg_voting_config_file); + m_no_password_confirmations = command_line::get_arg(vm, arg_no_password_confirmations); + } //---------------------------------------------------------------------------------------------------- + +#define PASSWORD_CONFIRMATION_ATTEMPTS 3 +bool simple_wallet::check_password_for_operation() +{ + if (m_no_password_confirmations) + return true; + for (size_t i = 0; i != PASSWORD_CONFIRMATION_ATTEMPTS; i++) + { + tools::password_container pass_container; + if (!pass_container.read_password("Enter password to confirm operation:\n")) + { + fail_msg_writer() << "Failed to read password"; + return false; + } + if (get_hash_from_pass_and_salt(pass_container.password(), m_password_salt) != m_password_hash) + { + fail_msg_writer() << "Wrong password"; + continue; + } + return true; + } + + fail_msg_writer() << "Confirmation failed with " << PASSWORD_CONFIRMATION_ATTEMPTS << " attempts"; + return false; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon() { if (!m_wallet->check_connection()) @@ -1529,6 +1567,7 @@ bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id) //---------------------------------------------------------------------------------------------------- bool simple_wallet::transfer(const std::vector &args_) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!try_connect_to_daemon()) return true; @@ -1692,6 +1731,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_seed(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); success_msg_writer() << "Please enter a password to secure this seed. Securing your seed is HIGHLY recommended. Leave password blank to stay unsecured."; success_msg_writer(true) << "Remember, restoring a wallet from Secured Seed can only be done if you know its password."; @@ -1715,6 +1755,7 @@ bool simple_wallet::show_seed(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::spendkey(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); message_writer(epee::log_space::console_color_red, true, std::string()) << "WARNING! Anyone who knows the following secret key can access your wallet and spend your coins."; @@ -1727,6 +1768,7 @@ bool simple_wallet::spendkey(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::viewkey(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); message_writer(epee::log_space::console_color_yellow, false, std::string()) << "WARNING! Anyone who knows the following secret key can view your wallet (but can not spend your coins)."; @@ -1924,6 +1966,7 @@ bool simple_wallet::list_outputs(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sign_transfer(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); if (m_wallet->is_watch_only()) { fail_msg_writer() << "You can't sign transaction in watch-only wallet"; @@ -1997,6 +2040,7 @@ bool simple_wallet::tor_disable(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::deploy_new_asset(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); asset_descriptor_base adb = AUTO_VAL_INIT(adb); if (!args.size() || args.size() > 1) @@ -2034,7 +2078,7 @@ bool simple_wallet::deploy_new_asset(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::emit_asset(const std::vector &args) { - + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 2) { @@ -2089,6 +2133,7 @@ bool simple_wallet::emit_asset(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::burn_asset(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 2) { @@ -2137,6 +2182,7 @@ bool simple_wallet::burn_asset(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::update_asset(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 2) { @@ -2186,6 +2232,7 @@ bool simple_wallet::update_asset(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::add_custom_asset_id(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!args.size() || args.size() > 1) { @@ -2221,6 +2268,7 @@ bool simple_wallet::add_custom_asset_id(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::generate_ionic_swap_proposal(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 2) @@ -2309,6 +2357,7 @@ bool simple_wallet::get_ionic_swap_proposal_info(const std::vector //---------------------------------------------------------------------------------------------------- bool simple_wallet::accept_ionic_swap_proposal(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (args.size() != 1) @@ -2350,6 +2399,7 @@ bool simple_wallet::accept_ionic_swap_proposal(const std::vector &a //---------------------------------------------------------------------------------------------------- bool simple_wallet::remove_custom_asset_id(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); if (!args.size() || args.size() > 1) { @@ -2380,6 +2430,7 @@ bool simple_wallet::remove_custom_asset_id(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector &args) { + CONFIRM_WITH_PASSWORD(); SIMPLE_WALLET_BEGIN_TRY_ENTRY(); bool r = false; if (args.size() < 3 || args.size() > 4) @@ -2623,6 +2674,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_disable_tor_relay); command_line::add_arg(desc_params, arg_set_timeout); command_line::add_arg(desc_params, arg_voting_config_file); + command_line::add_arg(desc_params, arg_no_password_confirmations); + diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 8f353bcf..81958f18 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -110,6 +110,8 @@ namespace currency bool try_connect_to_daemon(); std::string get_tocken_info_string(const crypto::public_key& asset_id, uint64_t& decimal_point); bool print_wti(const tools::wallet_public::wallet_transfer_info& wti); + bool check_password_for_operation(); + crypto::hash get_hash_from_pass_and_salt(const std::string& pass, uint64_t salt); //----------------- i_wallet2_callback --------------------- virtual void on_new_block(uint64_t height, const currency::block& block) override; @@ -189,6 +191,10 @@ namespace currency bool m_disable_tor; std::string m_restore_wallet; std::string m_voting_config_file; + bool m_no_password_confirmations = false; + + crypto::hash m_password_hash; + uint64_t m_password_salt; epee::console_handlers_binder m_cmd_binder; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 031229e3..bc9650a1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -640,8 +640,17 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t auto it = m_key_images.find(ki); if (it != m_key_images.end()) { + // Issue that has been discovered by Luke Parker (twitter: @kayabaNerve) + // An attacker can quickly issue transaction that use same outputs ephemeral keys + same tx key, as a result both + // transaction's outputs would have same key image, so the wallet should have smart approach to this situation, ie + // use output that offer biggest output value.(tokens?) + + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size()); const transfer_details& local_td = m_transfers[it->second]; + + + std::stringstream ss; ss << "tx " << ptc.tx_hash() << " @ block " << height << " has output #" << o << " with key image " << ki << " that has already been seen in output #" << local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx) << " @ block " << local_td.m_spent_height << @@ -3414,10 +3423,13 @@ bool wallet2::balance(std::list& balances, u auto it_cust = custom_assets_local.find(item.first); if(it_cust == custom_assets_local.end()) { + if(!m_use_assets_whitelisting) + continue; + auto it_local = m_whitelisted_assets.find(item.first); - if(it_local == m_whitelisted_assets.end()) + if(it_local == m_whitelisted_assets.end()) { - WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_0); + WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_1); continue; } else @@ -3637,7 +3649,7 @@ std::string wallet2::get_balance_str() const balance(balances, mined); for (const tools::wallet_public::asset_balance_entry& b : balances) { - ss << " " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point); + ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point); if (b.total == b.unlocked) ss << " "; else @@ -5466,17 +5478,19 @@ bool wallet2::create_ionic_swap_proposal(const wallet_public::ionic_swap_proposa { std::vector selected_transfers_for_template; - build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template); + return build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template); //const uint32_t mask_to_mark_escrow_template_locked_transfers = WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION; //mark_transfers_with_flag(selected_transfers_for_template, mask_to_mark_escrow_template_locked_transfers, "preparing ionic_swap"); - return true; + //return true; } //---------------------------------------------------------------------------------------------------- bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal_info& proposal_detais, const currency::account_public_address& destination_addr, wallet_public::ionic_swap_proposal& proposal, std::vector& selected_transfers) { + WLT_THROW_IF_FALSE_WITH_CODE(proposal_detais.fee_paid_by_a >= get_current_minimum_network_fee(), "Error at build_ionic_swap_template, ", API_RETURN_CODE_WALLET_FEE_TOO_LOW); + construct_tx_param ctp = get_default_construct_tx_param(); ctp.fake_outputs_count = proposal_detais.mixins; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 0e42bc0b..6f05bd9c 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -153,6 +153,7 @@ namespace tools uint64_t m_height_of_start_sync = 0; std::atomic m_last_sync_percent = 0; mutable uint64_t m_current_wallet_file_size = 0; + bool m_use_assets_whitelisting = true; //=============================================================== @@ -216,6 +217,7 @@ namespace tools a & m_custom_assets; a & m_rollback_events; a & m_whitelisted_assets; + a & m_use_assets_whitelisting; } }; @@ -646,6 +648,7 @@ namespace tools construct_tx_param get_default_construct_tx_param_inital(); void set_disable_tor_relay(bool disable); uint64_t get_default_fee() {return TX_DEFAULT_FEE;} + uint64_t get_current_minimum_network_fee() { return TX_DEFAULT_FEE; } void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true); bool add_custom_asset_id(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor); @@ -890,7 +893,6 @@ private: bool m_use_deffered_global_outputs; bool m_disable_tor_relay; - bool m_use_assets_whitelisting = true; mutable current_operation_context m_current_context; std::string m_votes_config_path; diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 07cb7f22..bfab00d5 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -731,7 +731,7 @@ if (!(cond)) { \ exception_handler(); \ std::stringstream ss; \ - ss << std::endl << mess; \ + ss << std::endl << "[" << error_code << "]" << mess ; \ LOG_ERROR(#cond << ". THROW EXCEPTION: " << error_code << ss.str()); \ tools::error::throw_wallet_ex(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ss.str(), error_code); \ } diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 4255d8e3..14610e9b 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -1805,6 +1805,12 @@ std::string wallets_manager::reset_wallet_password(uint64_t wallet_id, const std else return API_RETURN_CODE_FAIL; } +std::string wallets_manager::use_whitelisting(uint64_t wallet_id, bool use) +{ + GET_WALLET_OPT_BY_ID(wallet_id, w); + w.w->get()->set_use_assets_whitelisting(use); + return API_RETURN_CODE_OK; +} std::string wallets_manager::add_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor) { GET_WALLET_OPT_BY_ID(wallet_id, w); diff --git a/src/wallet/wallets_manager.h b/src/wallet/wallets_manager.h index 56f97885..9f940fed 100644 --- a/src/wallet/wallets_manager.h +++ b/src/wallet/wallets_manager.h @@ -137,6 +137,7 @@ public: std::string get_wallet_restore_info(uint64_t wallet_id, std::string& seed_phrase, const std::string& seed_password); std::string backup_wallet(uint64_t wallet_id, const std::wstring& path); std::string reset_wallet_password(uint64_t wallet_id, const std::string& pass); + std::string use_whitelisting(uint64_t wallet_id, bool use); std::string is_wallet_password_valid(uint64_t wallet_id, const std::string& pass); std::string create_ionic_swap_proposal(uint64_t wallet_id, const tools::wallet_public::create_ionic_swap_proposal_request& proposal, std::string& result_proposal_hex); std::string get_ionic_swap_proposal_info(uint64_t wallet_id, std::string&raw_tx_template_hex, tools::wallet_public::ionic_swap_proposal_info& proposal);