diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/api/wallet.cpp | 157 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 10 | ||||
-rw-r--r-- | src/wallet/api/wallet2_api.h | 36 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 3 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 1 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 89 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 5 | ||||
-rw-r--r-- | src/wallet/wallet_args.cpp | 5 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 18 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server_error_codes.h | 1 |
10 files changed, 235 insertions, 90 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 1711db482..e632b8d23 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1407,8 +1407,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat // - unconfirmed_transfer_details; // - confirmed_transfer_details) -PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, - PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices) +PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<string> &dst_addr, const string &payment_id, optional<std::vector<uint64_t>> amount, uint32_t mixin_count, PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices) { clearStatus(); @@ -1429,75 +1428,75 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const PendingTransactionImpl * transaction = new PendingTransactionImpl(*this); do { - if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) { - // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982 - setStatusError(tr("Invalid destination address")); + std::vector<uint8_t> extra; + std::string extra_nonce; + vector<cryptonote::tx_destination_entry> dsts; + if (!amount && dst_addr.size() > 1) { + setStatusError(tr("Sending all requires one destination address")); break; } - - - std::vector<uint8_t> extra; - // if dst_addr is not an integrated address, parse payment_id - if (!info.has_payment_id && !payment_id.empty()) { - // copy-pasted from simplewallet.cpp:2212 + if (amount && (dst_addr.size() != (*amount).size())) { + setStatusError(tr("Destinations and amounts are unequal")); + break; + } + if (!payment_id.empty()) { crypto::hash payment_id_long; - bool r = tools::wallet2::parse_long_payment_id(payment_id, payment_id_long); - if (r) { - std::string extra_nonce; + if (tools::wallet2::parse_long_payment_id(payment_id, payment_id_long)) { cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long); - r = add_extra_nonce_to_tx_extra(extra, extra_nonce); } else { - r = tools::wallet2::parse_short_payment_id(payment_id, info.payment_id); - if (r) { - std::string extra_nonce; - set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id); - r = add_extra_nonce_to_tx_extra(extra, extra_nonce); - } - } - - if (!r) { - setStatusError(tr("payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id); + setStatusError(tr("payment id has invalid format, expected 64 character hex string: ") + payment_id); break; } } - else if (info.has_payment_id) { - std::string extra_nonce; - set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id); - bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce); - if (!r) { - setStatusError(tr("Failed to add short payment id: ") + epee::string_tools::pod_to_hex(info.payment_id)); + bool error = false; + for (size_t i = 0; i < dst_addr.size() && !error; i++) { + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr[i])) { + // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982 + setStatusError(tr("Invalid destination address")); + error = true; break; } - } - - - //std::vector<tools::wallet2::pending_tx> ptx_vector; + if (info.has_payment_id) { + if (!extra_nonce.empty()) { + setStatusError(tr("a single transaction cannot use more than one payment id")); + error = true; + break; + } + set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id); + } - try { if (amount) { - vector<cryptonote::tx_destination_entry> dsts; cryptonote::tx_destination_entry de; - de.original = dst_addr; + de.original = dst_addr[i]; de.addr = info.address; - de.amount = *amount; + de.amount = (*amount)[i]; de.is_subaddress = info.is_subaddress; de.is_integrated = info.has_payment_id; dsts.push_back(de); - transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, - adjusted_priority, - extra, subaddr_account, subaddr_indices); } else { - // for the GUI, sweep_all (i.e. amount set as "(all)") will always sweep all the funds in all the addresses - if (subaddr_indices.empty()) - { + if (subaddr_indices.empty()) { for (uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index) subaddr_indices.insert(index); } + } + } + if (error) { + break; + } + if (!extra_nonce.empty() && !add_extra_nonce_to_tx_extra(extra, extra_nonce)) { + setStatusError(tr("failed to set up payment id, though it was decoded correctly")); + break; + } + try { + if (amount) { + transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, + adjusted_priority, + extra, subaddr_account, subaddr_indices); + } else { transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */, - adjusted_priority, - extra, subaddr_account, subaddr_indices); + adjusted_priority, + extra, subaddr_account, subaddr_indices); } - pendingTxPostProcess(transaction); if (multisig().isMultisig) { @@ -1574,6 +1573,13 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const return transaction; } +PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, + PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices) + +{ + return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices); +} + PendingTransaction *WalletImpl::createSweepUnmixableTransaction() { @@ -1697,6 +1703,19 @@ void WalletImpl::setDefaultMixin(uint32_t arg) m_wallet->default_mixin(arg); } +bool WalletImpl::setCacheAttribute(const std::string &key, const std::string &val) +{ + m_wallet->set_attribute(key, val); + return true; +} + +std::string WalletImpl::getCacheAttribute(const std::string &key) const +{ + std::string value; + m_wallet->get_attribute(key, value); + return value; +} + bool WalletImpl::setUserNote(const std::string &txid, const std::string ¬e) { cryptonote::blobdata txid_data; @@ -1729,18 +1748,27 @@ std::string WalletImpl::getTxKey(const std::string &txid_str) const crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; - if (m_wallet->get_tx_key(txid, tx_key, additional_tx_keys)) + try { clearStatus(); - std::ostringstream oss; - oss << epee::string_tools::pod_to_hex(tx_key); - for (size_t i = 0; i < additional_tx_keys.size(); ++i) - oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); - return oss.str(); + if (m_wallet->get_tx_key(txid, tx_key, additional_tx_keys)) + { + clearStatus(); + std::ostringstream oss; + oss << epee::string_tools::pod_to_hex(tx_key); + for (size_t i = 0; i < additional_tx_keys.size(); ++i) + oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); + return oss.str(); + } + else + { + setStatusError(tr("no tx keys found for this txid")); + return ""; + } } - else + catch (const std::exception &e) { - setStatusError(tr("no tx keys found for this txid")); + setStatusError(e.what()); return ""; } } @@ -2419,6 +2447,23 @@ uint64_t WalletImpl::coldKeyImageSync(uint64_t &spent, uint64_t &unspent) { return m_wallet->cold_key_image_sync(spent, unspent); } + +void WalletImpl::deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) +{ + boost::optional<crypto::hash8> payment_id_param = boost::none; + if (!paymentId.empty()) + { + crypto::hash8 payment_id; + bool res = tools::wallet2::parse_short_payment_id(paymentId, payment_id); + if (!res) + { + throw runtime_error("Invalid payment ID"); + } + payment_id_param = payment_id; + } + + m_wallet->device_show_address(accountIndex, addressIndex, payment_id_param); +} } // namespace namespace Bitmonero = Monero; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 9e07b6e19..331bf4b38 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -149,6 +149,11 @@ public: bool hasMultisigPartialKeyImages() const override; PendingTransaction* restoreMultisigTransaction(const std::string& signData) override; + PendingTransaction * createTransactionMultDest(const std::vector<std::string> &dst_addr, const std::string &payment_id, + optional<std::vector<uint64_t>> amount, uint32_t mixin_count, + PendingTransaction::Priority priority = PendingTransaction::Priority_Low, + uint32_t subaddr_account = 0, + std::set<uint32_t> subaddr_indices = {}) override; PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, PendingTransaction::Priority priority = PendingTransaction::Priority_Low, @@ -168,6 +173,10 @@ public: virtual void setListener(WalletListener * l) override; virtual uint32_t defaultMixin() const override; virtual void setDefaultMixin(uint32_t arg) override; + + virtual bool setCacheAttribute(const std::string &key, const std::string &val) override; + virtual std::string getCacheAttribute(const std::string &key) const override; + virtual bool setUserNote(const std::string &txid, const std::string ¬e) override; virtual std::string getUserNote(const std::string &txid) const override; virtual std::string getTxKey(const std::string &txid) const override; @@ -201,6 +210,7 @@ public: virtual bool unlockKeysFile() override; virtual bool isKeysFileLocked() override; virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override; + virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) override; private: void clearStatus() const; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 0af3b1867..e543a115b 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -812,6 +812,26 @@ struct Wallet * @return PendingTransaction */ virtual PendingTransaction* restoreMultisigTransaction(const std::string& signData) = 0; + + /*! + * \brief createTransactionMultDest creates transaction with multiple destinations. if dst_addr is an integrated address, payment_id is ignored + * \param dst_addr vector of destination address as string + * \param payment_id optional payment_id, can be empty string + * \param amount vector of amounts + * \param mixin_count mixin count. if 0 passed, wallet will use default value + * \param subaddr_account subaddress account from which the input funds are taken + * \param subaddr_indices set of subaddress indices to use for transfer or sweeping. if set empty, all are chosen when sweeping, and one or more are automatically chosen when transferring. after execution, returns the set of actually used indices + * \param priority + * \return PendingTransaction object. caller is responsible to check PendingTransaction::status() + * after object returned + */ + + virtual PendingTransaction * createTransactionMultDest(const std::vector<std::string> &dst_addr, const std::string &payment_id, + optional<std::vector<uint64_t>> amount, uint32_t mixin_count, + PendingTransaction::Priority = PendingTransaction::Priority_Low, + uint32_t subaddr_account = 0, + std::set<uint32_t> subaddr_indices = {}) = 0; + /*! * \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored * \param dst_addr destination address as string @@ -891,6 +911,19 @@ struct Wallet virtual void setDefaultMixin(uint32_t arg) = 0; /*! + * \brief setCacheAttribute - attach an arbitrary string to a wallet cache attribute + * \param key - the key + * \param val - the value + * \return true if successful, false otherwise + */ + virtual bool setCacheAttribute(const std::string &key, const std::string &val) = 0; + /*! + * \brief getCacheAttribute - return an arbitrary string attached to a wallet cache attribute + * \param key - the key + * \return the attached string, or empty string if there is none + */ + virtual std::string getCacheAttribute(const std::string &key) const = 0; + /*! * \brief setUserNote - attach an arbitrary string note to a txid * \param txid - the transaction id to attach the note to * \param note - the note @@ -1003,6 +1036,9 @@ struct Wallet //! cold-device protocol key image sync virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) = 0; + + //! shows address on device display + virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) = 0; }; /** diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index ef2ed2015..d589dcc75 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -227,9 +227,6 @@ std::string WalletManagerImpl::errorString() const void WalletManagerImpl::setDaemonAddress(const std::string &address) { - m_daemonAddress = address; - if(m_http_client.is_connected()) - m_http_client.disconnect(); m_http_client.set_server(address, boost::none); } diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 235f96e17..537fc5ba6 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -95,7 +95,6 @@ public: private: WalletManagerImpl() {} friend struct WalletManagerFactory; - std::string m_daemonAddress; epee::net_utils::http::http_simple_client m_http_client; std::string m_errorString; }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8f3f30da1..117ad4ea8 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -217,6 +217,8 @@ namespace add_reason(reason, "invalid input"); if (res.invalid_output) add_reason(reason, "invalid output"); + if (res.too_few_outputs) + add_reason(reason, "too few outputs"); if (res.too_big) add_reason(reason, "too big"); if (res.overspend) @@ -1140,7 +1142,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_devices_registered(false), m_device_last_key_image_sync(0), m_use_dns(true), - m_offline(false) + m_offline(false), + m_rpc_version(0) { } @@ -5157,6 +5160,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout) if (m_offline) { + m_rpc_version = 0; if (version) *version = 0; if (ssl) @@ -5166,6 +5170,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout) // TODO: Add light wallet version check. if(m_light_wallet) { + m_rpc_version = 0; if (version) *version = 0; if (ssl) @@ -5177,6 +5182,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout) boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex); if(!m_http_client.is_connected(ssl)) { + m_rpc_version = 0; m_node_rpc_proxy.invalidate(); if (!m_http_client.connect(std::chrono::milliseconds(timeout))) return false; @@ -5185,20 +5191,21 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout) } } - if (version) + if (!m_rpc_version) { cryptonote::COMMAND_RPC_GET_VERSION::request req_t = AUTO_VAL_INIT(req_t); cryptonote::COMMAND_RPC_GET_VERSION::response resp_t = AUTO_VAL_INIT(resp_t); bool r = invoke_http_json_rpc("/json_rpc", "get_version", req_t, resp_t); if(!r) { - *version = 0; + if(version) + *version = 0; return false; } - if (resp_t.status != CORE_RPC_STATUS_OK) - *version = 0; - else - *version = resp_t.version; + if (resp_t.status == CORE_RPC_STATUS_OK) + m_rpc_version = resp_t.version; } + if (version) + *version = m_rpc_version; return true; } @@ -6118,7 +6125,7 @@ void wallet2::commit_tx(pending_tx& ptx) amount_in += m_transfers[idx].amount(); } add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount, ptx.construction_data.subaddr_account, ptx.construction_data.subaddr_indices); - if (store_tx_info()) + if (store_tx_info() && ptx.tx_key != crypto::null_skey) { m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys)); @@ -6307,7 +6314,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin // normally, the tx keys are saved in commit_tx, when the tx is actually sent to the daemon. // we can't do that here since the tx will be sent from the compromised wallet, which we don't want // to see that info, so we save it here - if (store_tx_info()) + if (store_tx_info() && ptx.tx_key != crypto::null_skey) { const crypto::hash txid = get_transaction_hash(ptx.tx); m_tx_keys.insert(std::make_pair(txid, tx_key)); @@ -6931,7 +6938,7 @@ uint64_t wallet2::get_base_fee() const else return m_light_wallet_per_kb_fee; } - bool use_dyn_fee = use_fork_rules(HF_VERSION_DYNAMIC_FEE, -720 * 1); + bool use_dyn_fee = use_fork_rules(HF_VERSION_DYNAMIC_FEE, -30 * 1); if (!use_dyn_fee) return FEE_PER_KB; @@ -6962,7 +6969,7 @@ int wallet2::get_fee_algorithm() const return 3; if (use_fork_rules(5, 0)) return 2; - if (use_fork_rules(3, -720 * 14)) + if (use_fork_rules(3, -30 * 14)) return 1; return 0; } @@ -7443,7 +7450,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_ order.resize(light_wallet_requested_outputs_count); for (size_t n = 0; n < order.size(); ++n) order[n] = n; - std::shuffle(order.begin(), order.end(), std::default_random_engine(crypto::rand<unsigned>())); + std::shuffle(order.begin(), order.end(), crypto::random_device{}); LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs with amounts " << print_money(td.is_rct() ? 0 : td.amount())); @@ -7726,7 +7733,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> uint64_t num_found = 0; // if we have a known ring, use it - bool existing_ring_found = false; if (td.m_key_image_known && !td.m_key_image_partial) { std::vector<uint64_t> ring; @@ -7738,7 +7744,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> std::to_string(ring.size()) + ", it cannot be spent now with ring size " + std::to_string(fake_outputs_count + 1) + " as it is smaller: use a higher ring size"); bool own_found = false; - existing_ring_found = true; for (const auto &out: ring) { MINFO("Ring has output " << out); @@ -7984,7 +7989,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> outs.back().push_back(std::make_tuple(td.m_global_output_index, boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key, mask)); // then pick outs from an existing ring, if any - bool existing_ring_found = false; if (td.m_key_image_known && !td.m_key_image_partial) { std::vector<uint64_t> ring; @@ -8021,7 +8025,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> order.resize(requested_outputs_count); for (size_t n = 0; n < order.size(); ++n) order[n] = n; - std::shuffle(order.begin(), order.end(), std::default_random_engine(crypto::rand<unsigned>())); + std::shuffle(order.begin(), order.end(), crypto::random_device{}); LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs of size " << print_money(td.is_rct() ? 0 : td.amount())); for (size_t o = 0; o < requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o) @@ -8163,6 +8167,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent if (needed_money < found_money) { change_dts.addr = get_subaddress({subaddr_account, 0}); + change_dts.is_subaddress = subaddr_account != 0; change_dts.amount = found_money - needed_money; } @@ -10051,6 +10056,7 @@ void wallet2::cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_ setup_shim(&wallet_shim, this); aux_data.tx_recipients = dsts_info; aux_data.bp_version = use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1; + aux_data.hard_fork = get_current_hard_fork(); dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data); tx_device_aux = aux_data.tx_device_aux; @@ -10078,6 +10084,35 @@ uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { return import_res; } //---------------------------------------------------------------------------------------------------- +void wallet2::device_show_address(uint32_t account_index, uint32_t address_index, const boost::optional<crypto::hash8> &payment_id) +{ + if (!key_on_device()) + { + return; + } + + auto & hwdev = get_account().get_device(); + hwdev.display_address(subaddress_index{account_index, address_index}, payment_id); +} +//---------------------------------------------------------------------------------------------------- +uint8_t wallet2::get_current_hard_fork() +{ + if (m_offline) + return 0; + + cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req_t = AUTO_VAL_INIT(req_t); + cryptonote::COMMAND_RPC_HARD_FORK_INFO::response resp_t = AUTO_VAL_INIT(resp_t); + + m_daemon_rpc_mutex.lock(); + req_t.version = 0; + bool r = net_utils::invoke_http_json_rpc("/json_rpc", "hard_fork_info", req_t, resp_t, m_http_client, rpc_timeout); + m_daemon_rpc_mutex.unlock(); + THROW_WALLET_EXCEPTION_IF(!r, tools::error::no_connection_to_daemon, "hard_fork_info"); + THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, tools::error::daemon_busy, "hard_fork_info"); + THROW_WALLET_EXCEPTION_IF(resp_t.status != CORE_RPC_STATUS_OK, tools::error::wallet_generic_rpc_error, "hard_fork_info", m_trusted_daemon ? resp_t.status : "daemon error"); + return resp_t.version; +} +//---------------------------------------------------------------------------------------------------- void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const { boost::optional<std::string> result = m_node_rpc_proxy.get_earliest_height(version, earliest_height); @@ -10276,6 +10311,8 @@ bool wallet2::get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx if (i == m_tx_keys.end()) return false; tx_key = i->second; + if (tx_key == crypto::null_skey) + return false; const auto j = m_additional_tx_keys.find(txid); if (j != m_additional_tx_keys.end()) additional_tx_keys = j->second; @@ -10287,6 +10324,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s bool r = get_tx_key_cached(txid, tx_key, additional_tx_keys); if (r) { + MDEBUG("tx key cached for txid: " << txid); return true; } @@ -10348,13 +10386,18 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s dev_cold->get_tx_key(tx_keys, tx_key_data, m_account.get_keys().m_view_secret_key); if (tx_keys.empty()) { + MDEBUG("Empty tx keys for txid: " << txid); + return false; + } + + if (tx_keys[0] == crypto::null_skey) + { return false; } tx_key = tx_keys[0]; tx_keys.erase(tx_keys.begin()); additional_tx_keys = tx_keys; - return true; } //---------------------------------------------------------------------------------------------------- @@ -11387,12 +11430,13 @@ void wallet2::set_attribute(const std::string &key, const std::string &value) m_attributes[key] = value; } -std::string wallet2::get_attribute(const std::string &key) const +bool wallet2::get_attribute(const std::string &key, std::string &value) const { std::unordered_map<std::string, std::string>::const_iterator i = m_attributes.find(key); if (i == m_attributes.end()) - return std::string(); - return i->second; + return false; + value = i->second; + return true; } void wallet2::set_description(const std::string &description) @@ -11402,7 +11446,10 @@ void wallet2::set_description(const std::string &description) std::string wallet2::get_description() const { - return get_attribute(ATTRIBUTE_DESCRIPTION); + std::string s; + if (get_attribute(ATTRIBUTE_DESCRIPTION, s)) + return s; + return ""; } const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags() diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 921c150cb..a6d042297 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -843,6 +843,7 @@ private: void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux); void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux); uint64_t cold_key_image_sync(uint64_t &spent, uint64_t &unspent); + void device_show_address(uint32_t account_index, uint32_t address_index, const boost::optional<crypto::hash8> &payment_id); bool parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const; bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL); bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL); @@ -1094,6 +1095,7 @@ private: size_t get_num_transfer_details() const { return m_transfers.size(); } const transfer_details &get_transfer_details(size_t idx) const; + uint8_t get_current_hard_fork(); void get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const; bool use_fork_rules(uint8_t version, int64_t early_blocks = 0) const; int get_fee_algorithm() const; @@ -1247,7 +1249,7 @@ private: */ const char* const ATTRIBUTE_DESCRIPTION = "wallet2.description"; void set_attribute(const std::string &key, const std::string &value); - std::string get_attribute(const std::string &key) const; + bool get_attribute(const std::string &key, std::string &value) const; crypto::public_key get_multisig_signer_public_key(const crypto::secret_key &spend_skey) const; crypto::public_key get_multisig_signer_public_key() const; @@ -1504,6 +1506,7 @@ private: uint64_t m_device_last_key_image_sync; bool m_use_dns; bool m_offline; + uint32_t m_rpc_version; // Aux transaction data from device std::unordered_map<crypto::hash, std::string> m_tx_device; diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index a4bb342ca..9da9d109c 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -206,7 +206,10 @@ namespace wallet_args if (!command_line::is_arg_defaulted(vm, arg_log_level)) MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level)); else - MINFO("Setting log levels = " << getenv("MONERO_LOGS")); + { + const char *logs = getenv("MONERO_LOGS"); + MINFO("Setting log levels = " << (logs ? logs : "<default>")); + } MINFO(wallet_args::tr("Logging to: ") << log_path); Print(print) << boost::format(wallet_args::tr("Logging to %s")) % log_path; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 0e2a34470..844ecf90c 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -247,7 +247,9 @@ namespace tools m_net_server.set_threads_prefix("RPC"); auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); }; return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( - rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), + rng, std::move(bind_port), std::move(rpc_config->bind_ip), + std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4), + std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) ); } @@ -1811,14 +1813,12 @@ namespace tools wallet2::transfer_container transfers; m_wallet->get_transfers(transfers); - bool transfers_found = false; for (const auto& td : transfers) { if (!filter || available != td.m_spent) { if (req.account_index != td.m_subaddr_index.major || (!req.subaddr_indices.empty() && req.subaddr_indices.count(td.m_subaddr_index.minor) == 0)) continue; - transfers_found = true; wallet_rpc::transfer_details rpc_transfers; rpc_transfers.amount = td.amount(); rpc_transfers.spent = td.m_spent; @@ -2104,7 +2104,12 @@ namespace tools return false; } - res.value = m_wallet->get_attribute(req.key); + if (!m_wallet->get_attribute(req.key, res.value)) + { + er.code = WALLET_RPC_ERROR_CODE_ATTRIBUTE_NOT_FOUND; + er.message = "Attribute not found."; + return false; + } return true; } bool wallet_rpc_server::on_get_tx_key(const wallet_rpc::COMMAND_RPC_GET_TX_KEY::request& req, wallet_rpc::COMMAND_RPC_GET_TX_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx) @@ -4086,9 +4091,8 @@ namespace tools } } - er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; - er.message = std::string("Invalid address"); - return false; + res.valid = false; + return true; } //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_set_daemon(const wallet_rpc::COMMAND_RPC_SET_DAEMON::request& req, wallet_rpc::COMMAND_RPC_SET_DAEMON::response& res, epee::json_rpc::error& er, const connection_context *ctx) diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index 011d146d4..9434fbc3e 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_rpc_server_error_codes.h @@ -75,3 +75,4 @@ #define WALLET_RPC_ERROR_CODE_SIGN_UNSIGNED -42 #define WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC -43 #define WALLET_RPC_ERROR_CODE_INVALID_LOG_LEVEL -44 +#define WALLET_RPC_ERROR_CODE_ATTRIBUTE_NOT_FOUND -45 |