diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/api/wallet.cpp | 13 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 5 | ||||
-rw-r--r-- | src/wallet/api/wallet2_api.h | 7 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 4 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 5 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 109 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 18 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 22 |
8 files changed, 119 insertions, 64 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 66e248427..73ab88a9f 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -938,13 +938,13 @@ string WalletImpl::keysFilename() const return m_wallet->get_keys_file(); } -bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet) +bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet, const std::string &proxy_address) { clearStatus(); m_wallet->set_light_wallet(lightWallet); if(daemon_username != "") m_daemon_login.emplace(daemon_username, daemon_password); - return doInit(daemon_address, upper_transaction_size_limit, use_ssl); + return doInit(daemon_address, proxy_address, upper_transaction_size_limit, use_ssl); } bool WalletImpl::lightWalletLogin(bool &isNewWallet) const @@ -2088,6 +2088,11 @@ bool WalletImpl::trustedDaemon() const return m_wallet->is_trusted_daemon(); } +bool WalletImpl::setProxy(const std::string &address) +{ + return m_wallet->set_proxy(address); +} + bool WalletImpl::watchOnly() const { return m_wallet->watch_only(); @@ -2241,9 +2246,9 @@ void WalletImpl::pendingTxPostProcess(PendingTransactionImpl * pending) pending->m_pending_tx = exported_txs.ptx; } -bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl) +bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit, bool ssl) { - if (!m_wallet->init(daemon_address, m_daemon_login, boost::asio::ip::tcp::endpoint{}, upper_transaction_size_limit)) + if (!m_wallet->init(daemon_address, m_daemon_login, proxy_address, 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 43d85b704..caf1e9ed4 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -102,11 +102,12 @@ public: bool store(const std::string &path) override; std::string filename() const override; std::string keysFilename() const override; - 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 use_ssl = false, bool lightWallet = false) override; + 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 use_ssl = false, bool lightWallet = false, const std::string &proxy_address = "") override; bool connectToDaemon() override; ConnectionStatus connected() const override; void setTrustedDaemon(bool arg) override; bool trustedDaemon() const override; + bool setProxy(const std::string &address) override; uint64_t balance(uint32_t accountIndex = 0) const override; uint64_t unlockedBalance(uint32_t accountIndex = 0) const override; uint64_t blockChainHeight() const override; @@ -225,7 +226,7 @@ private: void stopRefresh(); bool isNewWallet() const; void pendingTxPostProcess(PendingTransactionImpl * pending); - bool doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false); + bool doInit(const std::string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false); private: friend class PendingTransactionImpl; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index e2f96a069..50df7e5dd 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -533,9 +533,10 @@ struct Wallet * \param daemon_username * \param daemon_password * \param lightWallet - start wallet in light mode, connect to a openmonero compatible server. + * \param proxy_address - set proxy address, empty string to disable * \return - true on success */ - virtual 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 use_ssl = false, bool lightWallet = false) = 0; + virtual 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 use_ssl = false, bool lightWallet = false, const std::string &proxy_address = "") = 0; /*! * \brief createWatchOnly - Creates a watch only wallet @@ -594,6 +595,7 @@ struct Wallet virtual ConnectionStatus connected() const = 0; virtual void setTrustedDaemon(bool arg) = 0; virtual bool trustedDaemon() const = 0; + virtual bool setProxy(const std::string &address) = 0; virtual uint64_t balance(uint32_t accountIndex = 0) const = 0; uint64_t balanceAll() const { uint64_t result = 0; @@ -1298,6 +1300,9 @@ struct WalletManager std::string subdir, const char *buildtag = nullptr, const char *current_version = nullptr); + + //! sets proxy address, empty string to disable + virtual bool setProxy(const std::string &address) = 0; }; diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 69d17eb02..900fe91e5 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -375,6 +375,10 @@ std::tuple<bool, std::string, std::string, std::string, std::string> WalletManag return std::make_tuple(false, "", "", "", ""); } +bool WalletManagerImpl::setProxy(const std::string &address) +{ + return m_http_client.set_proxy(address); +} ///////////////////// WalletManagerFactory implementation ////////////////////// WalletManager *WalletManagerFactory::getWalletManager() diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index ca8e9ada2..2f603b0a9 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -30,7 +30,7 @@ #include "wallet/api/wallet2_api.h" -#include "net/http_client.h" +#include "net/http.h" #include <string> namespace Monero { @@ -92,11 +92,12 @@ public: bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true) override; bool stopMining() override; std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override; + bool setProxy(const std::string &address) override; private: WalletManagerImpl() {} friend struct WalletManagerFactory; - epee::net_utils::http::http_simple_client m_http_client; + net::http::client m_http_client; std::string m_errorString; }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d7ed3e999..353f20b51 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -48,6 +48,7 @@ using namespace epee; #include "wallet_rpc_helpers.h" #include "wallet2.h" #include "cryptonote_basic/cryptonote_format_utils.h" +#include "net/parse.h" #include "rpc/core_rpc_server_commands_defs.h" #include "rpc/core_rpc_server_error_codes.h" #include "rpc/rpc_payment_signature.h" @@ -440,30 +441,14 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl ); } - boost::asio::ip::tcp::endpoint proxy{}; + std::string proxy; if (use_proxy) { - namespace ip = boost::asio::ip; - - const auto proxy_address = command_line::get_arg(vm, opts.proxy); - - boost::string_ref proxy_port{proxy_address}; - boost::string_ref proxy_host = proxy_port.substr(0, proxy_port.rfind(":")); - if (proxy_port.size() == proxy_host.size()) - proxy_host = "127.0.0.1"; - else - proxy_port = proxy_port.substr(proxy_host.size() + 1); - - uint16_t port_value = 0; + proxy = command_line::get_arg(vm, opts.proxy); THROW_WALLET_EXCEPTION_IF( - !epee::string_tools::get_xtype_from_string(port_value, std::string{proxy_port}), + !net::get_tcp_endpoint(proxy), tools::error::wallet_internal_error, - std::string{"Invalid port specified for --"} + opts.proxy.name - ); - - boost::system::error_code error{}; - proxy = ip::tcp::endpoint{ip::address::from_string(std::string{proxy_host}, error), port_value}; - THROW_WALLET_EXCEPTION_IF(bool(error), tools::error::wallet_internal_error, std::string{"Invalid IP address specified for --"} + opts.proxy.name); + std::string{"Invalid address specified for --"} + opts.proxy.name); } boost::optional<bool> trusted_daemon; @@ -488,7 +473,10 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl } std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended)); - wallet->init(std::move(daemon_address), std::move(login), std::move(proxy), 0, *trusted_daemon, std::move(ssl_options)); + if (!wallet->init(std::move(daemon_address), std::move(login), std::move(proxy), 0, *trusted_daemon, std::move(ssl_options))) + { + THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to initialize the wallet")); + } boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir); wallet->set_ring_database(ringdb_path.string()); wallet->get_message_store().set_options(vm); @@ -1125,7 +1113,7 @@ void wallet_device_callback::on_progress(const hw::device_progress& event) } wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory): - m_http_client(std::move(http_client_factory->create())), + m_http_client(http_client_factory->create()), m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), m_upper_transaction_weight_limit(0), @@ -1325,18 +1313,17 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u return ret; } //---------------------------------------------------------------------------------------------------- -bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, boost::asio::ip::tcp::endpoint proxy, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options) +bool wallet2::set_proxy(const std::string &address) +{ + return m_http_client->set_proxy(address); +} +//---------------------------------------------------------------------------------------------------- +bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, const std::string &proxy_address, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options) { + CHECK_AND_ASSERT_MES(set_proxy(proxy_address), false, "failed to set proxy address"); m_checkpoints.init_default_checkpoints(m_nettype); m_is_initialized = true; m_upper_transaction_weight_limit = upper_transaction_weight_limit; - if (proxy != boost::asio::ip::tcp::endpoint{}) - { - epee::net_utils::http::abstract_http_client* abstract_http_client = m_http_client.get(); - epee::net_utils::http::http_simple_client* http_simple_client = dynamic_cast<epee::net_utils::http::http_simple_client*>(abstract_http_client); - CHECK_AND_ASSERT_MES(http_simple_client != nullptr, false, "http_simple_client must be used to set proxy"); - http_simple_client->set_connector(net::socks::connector{std::move(proxy)}); - } return set_daemon(daemon_address, daemon_login, trusted_daemon, std::move(ssl_options)); } //---------------------------------------------------------------------------------------------------- @@ -4349,9 +4336,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st if (r) { + // Decrypt keys, using one of two possible methods if (encrypted_secret_keys) { + // First try the updated method m_account.decrypt_keys(key); + load_info.is_legacy_key_encryption = false; + + // Test address construction to see if decryption succeeded + const cryptonote::account_keys &keys = m_account.get_keys(); + hw::device &hwdev = m_account.get_device(); + if (!hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key) || !hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key)) + { + // Updated method failed; try the legacy method + // Note that we must first encrypt the keys again with the same IV + m_account.encrypt_keys_same_iv(key); + m_account.decrypt_legacy(key); + load_info.is_legacy_key_encryption = true; + } } else { @@ -5555,6 +5557,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass { clear(); prepare_file_names(wallet_); + MINFO("Keys file: " << m_keys_file); // determine if loading from file system or string buffer bool use_fs = !wallet_.empty(); @@ -11425,7 +11428,7 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]); } } - sig_str = std::string("OutProofV1"); + sig_str = std::string("OutProofV2"); } else { @@ -11461,7 +11464,7 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]); } } - sig_str = std::string("InProofV1"); + sig_str = std::string("InProofV2"); } const size_t num_sigs = shared_secret.size(); @@ -11540,8 +11543,14 @@ bool wallet2::check_tx_proof(const crypto::hash &txid, const cryptonote::account bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received) const { + // InProofV1, InProofV2, OutProofV1, OutProofV2 const bool is_out = sig_str.substr(0, 3) == "Out"; - const std::string header = is_out ? "OutProofV1" : "InProofV1"; + const std::string header = is_out ? sig_str.substr(0,10) : sig_str.substr(0,9); + int version = 2; // InProofV2 + if (is_out && sig_str.substr(8,2) == "V1") version = 1; // OutProofV1 + else if (is_out) version = 2; // OutProofV2 + else if (sig_str.substr(7,2) == "V1") version = 1; // InProofV1 + const size_t header_len = header.size(); THROW_WALLET_EXCEPTION_IF(sig_str.size() < header_len || sig_str.substr(0, header_len) != header, error::wallet_internal_error, "Signature header check error"); @@ -11588,27 +11597,27 @@ bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote if (is_out) { good_signature[0] = is_subaddress ? - crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], sig[0]) : - crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], sig[0]); + crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], sig[0], version) : + crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], sig[0], version); for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { good_signature[i + 1] = is_subaddress ? - crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) : - crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, boost::none, shared_secret[i + 1], sig[i + 1]); + crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, address.m_spend_public_key, shared_secret[i + 1], sig[i + 1], version) : + crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, boost::none, shared_secret[i + 1], sig[i + 1], version); } } else { good_signature[0] = is_subaddress ? - crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], sig[0]) : - crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], sig[0]); + crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], sig[0], version) : + crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], sig[0], version); for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { good_signature[i + 1] = is_subaddress ? - crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) : - crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], boost::none, shared_secret[i + 1], sig[i + 1]); + crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], address.m_spend_public_key, shared_secret[i + 1], sig[i + 1], version) : + crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], boost::none, shared_secret[i + 1], sig[i + 1], version); } } @@ -11746,7 +11755,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, std::ostringstream oss; boost::archive::portable_binary_oarchive ar(oss); ar << proofs << subaddr_spendkeys; - return "ReserveProofV1" + tools::base58::encode(oss.str()); + return "ReserveProofV2" + tools::base58::encode(oss.str()); } bool wallet2::check_reserve_proof(const cryptonote::account_public_address &address, const std::string &message, const std::string &sig_str, uint64_t &total, uint64_t &spent) @@ -11755,12 +11764,18 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address()); THROW_WALLET_EXCEPTION_IF(rpc_version < MAKE_CORE_RPC_VERSION(1, 0), error::wallet_internal_error, "Daemon RPC version is too old"); - static constexpr char header[] = "ReserveProofV1"; - THROW_WALLET_EXCEPTION_IF(!boost::string_ref{sig_str}.starts_with(header), error::wallet_internal_error, + static constexpr char header_v1[] = "ReserveProofV1"; + static constexpr char header_v2[] = "ReserveProofV2"; // assumes same length as header_v1 + THROW_WALLET_EXCEPTION_IF(!boost::string_ref{sig_str}.starts_with(header_v1) && !boost::string_ref{sig_str}.starts_with(header_v2), error::wallet_internal_error, "Signature header check error"); + int version = 2; // assume newest version + if (boost::string_ref{sig_str}.starts_with(header_v1)) + version = 1; + else if (boost::string_ref{sig_str}.starts_with(header_v2)) + version = 2; std::string sig_decoded; - THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header)), sig_decoded), error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header_v1)), sig_decoded), error::wallet_internal_error, "Signature decoding error"); std::istringstream iss(sig_decoded); @@ -11841,9 +11856,9 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx); // check singature for shared secret - ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, proof.shared_secret, proof.shared_secret_sig); + ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, proof.shared_secret, proof.shared_secret_sig, version); if (!ok && additional_tx_pub_keys.size() == tx.vout.size()) - ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[proof.index_in_tx], boost::none, proof.shared_secret, proof.shared_secret_sig); + ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[proof.index_in_tx], boost::none, proof.shared_secret, proof.shared_secret_sig, version); if (!ok) return false; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 712f91613..44ae342c3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -45,7 +45,7 @@ #include "cryptonote_basic/account.h" #include "cryptonote_basic/account_boost_serialization.h" #include "cryptonote_basic/cryptonote_basic_impl.h" -#include "net/http_client.h" +#include "net/http.h" #include "storages/http_abstract_invoke.h" #include "rpc/core_rpc_server_commands_defs.h" #include "cryptonote_basic/cryptonote_format_utils.h" @@ -219,6 +219,15 @@ private: friend class wallet_keys_unlocker; friend class wallet_device_callback; public: + // Contains data on how keys were loaded, primarily for unit test purposes + struct load_info_t { + bool is_legacy_key_encryption; + }; + + const load_info_t &get_load_info() const { + return load_info; + } + static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30); enum RefreshType { @@ -269,7 +278,7 @@ private: static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds); static bool query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1); - wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_simple_client_factory>(new epee::net_utils::http::http_simple_client_factory())); + wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_client_factory>(new net::http::client_factory())); ~wallet2(); struct multisig_info @@ -753,13 +762,14 @@ private: bool deinit(); bool init(std::string daemon_address = "http://localhost:8080", boost::optional<epee::net_utils::http::login> daemon_login = boost::none, - boost::asio::ip::tcp::endpoint proxy = {}, + const std::string &proxy = "", uint64_t upper_transaction_weight_limit = 0, bool trusted_daemon = true, epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect); bool set_daemon(std::string daemon_address = "http://localhost:8080", boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true, epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect); + bool set_proxy(const std::string &address); void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); } @@ -1407,6 +1417,8 @@ private: static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; } private: + load_info_t load_info; + /*! * \brief Stores wallet information to wallet file. * \param keys_file_name Name of wallet file diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index fcaaf7616..2391b51fd 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -80,7 +80,7 @@ namespace return pwd_container; } //------------------------------------------------------------------------------------------------------------------------------ - void set_confirmations(tools::wallet_rpc::transfer_entry &entry, uint64_t blockchain_height, uint64_t block_reward) + void set_confirmations(tools::wallet_rpc::transfer_entry &entry, uint64_t blockchain_height, uint64_t block_reward, uint64_t unlock_time) { if (entry.height >= blockchain_height || (entry.height == 0 && (!strcmp(entry.type.c_str(), "pending") || !strcmp(entry.type.c_str(), "pool")))) entry.confirmations = 0; @@ -91,6 +91,18 @@ namespace entry.suggested_confirmations_threshold = 0; else entry.suggested_confirmations_threshold = (entry.amount + block_reward - 1) / block_reward; + + if (unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER) + { + if (unlock_time > blockchain_height) + entry.suggested_confirmations_threshold = std::max(entry.suggested_confirmations_threshold, unlock_time - blockchain_height); + } + else + { + const uint64_t now = time(NULL); + if (unlock_time > now) + entry.suggested_confirmations_threshold = std::max(entry.suggested_confirmations_threshold, (unlock_time - now + DIFFICULTY_TARGET_V2 - 1) / DIFFICULTY_TARGET_V2); + } } } @@ -335,7 +347,7 @@ namespace tools entry.subaddr_index = pd.m_subaddr_index; entry.subaddr_indices.push_back(pd.m_subaddr_index); entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index); - set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward()); + set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time); } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd) @@ -365,7 +377,7 @@ namespace tools for (uint32_t i: pd.m_subaddr_indices) entry.subaddr_indices.push_back({pd.m_subaddr_account, i}); entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0}); - set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward()); + set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time); } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd) @@ -396,7 +408,7 @@ namespace tools for (uint32_t i: pd.m_subaddr_indices) entry.subaddr_indices.push_back({pd.m_subaddr_account, i}); entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0}); - set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward()); + set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_tx.unlock_time); } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &ppd) @@ -419,7 +431,7 @@ namespace tools entry.subaddr_index = pd.m_subaddr_index; entry.subaddr_indices.push_back(pd.m_subaddr_index); entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index); - set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward()); + set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time); } //------------------------------------------------------------------------------------------------------------------------------ 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, const connection_context *ctx) |