diff options
author | Dusan Klinec <dusan.klinec@gmail.com> | 2019-05-31 10:41:52 +0200 |
---|---|---|
committer | Dusan Klinec <dusan.klinec@gmail.com> | 2019-06-17 16:49:04 +0200 |
commit | f074b6b5715f90960e5ebf8d440101ba446d94b0 (patch) | |
tree | a25bbf87a3ae70430ebc3e73755a07ee708d2f8e | |
parent | Merge pull request #5548 (diff) | |
download | monero-f074b6b5715f90960e5ebf8d440101ba446d94b0.tar.xz |
device: show address on device display
- Trezor: support for device address display (subaddress, integrated address)
- Wallet::API support added
- Simplewallet:
- address device [<index>]
- address new <label> // shows address on device also
- integrated_address [device] <payment_id|address> // new optional "device" arg to display also on the device
m--------- | external/trezor-common | 0 | ||||
-rw-r--r-- | src/device/device.hpp | 1 | ||||
-rw-r--r-- | src/device/device_cold.hpp | 1 | ||||
-rw-r--r-- | src/device_trezor/device_trezor.cpp | 16 | ||||
-rw-r--r-- | src/device_trezor/device_trezor.hpp | 4 | ||||
-rw-r--r-- | src/device_trezor/trezor/protocol.cpp | 3 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 55 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 17 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 1 | ||||
-rw-r--r-- | src/wallet/api/wallet2_api.h | 3 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 30 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 2 |
12 files changed, 127 insertions, 6 deletions
diff --git a/external/trezor-common b/external/trezor-common -Subproject cb238cb1f134accc4200217d9511115a8f61c6c +Subproject 31a0073c62738827b48d725facd376687942912 diff --git a/src/device/device.hpp b/src/device/device.hpp index 866e2c676..215e97eb6 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -236,6 +236,7 @@ namespace hw { virtual bool compute_key_image(const cryptonote::account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const cryptonote::subaddress_index& received_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki) { return false; } virtual void computing_key_images(bool started) {}; virtual void set_network_type(cryptonote::network_type network_type) { } + virtual void display_address(const cryptonote::subaddress_index& index, const boost::optional<crypto::hash8> &payment_id) {} protected: device_mode mode; diff --git a/src/device/device_cold.hpp b/src/device/device_cold.hpp index 31b1504ab..22708c46a 100644 --- a/src/device/device_cold.hpp +++ b/src/device/device_cold.hpp @@ -47,6 +47,7 @@ namespace hw { std::vector<cryptonote::address_parse_info> tx_recipients; // as entered by user boost::optional<int> bp_version; // BP version to use boost::optional<unsigned> client_version; // Signing client version to use (testing) + boost::optional<uint8_t> hard_fork; // hard fork being used for the transaction }; class device_cold { diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index b1022dd9c..a77f6697f 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -200,6 +200,10 @@ namespace trezor { } } + void device_trezor::display_address(const cryptonote::subaddress_index& index, const boost::optional<crypto::hash8> &payment_id) { + get_address(index, payment_id, true); + } + /* ======================================================================= */ /* Helpers */ /* ======================================================================= */ @@ -209,8 +213,12 @@ namespace trezor { /* ======================================================================= */ std::shared_ptr<messages::monero::MoneroAddress> device_trezor::get_address( + const boost::optional<cryptonote::subaddress_index> & subaddress, + const boost::optional<crypto::hash8> & payment_id, + bool show_address, const boost::optional<std::vector<uint32_t>> & path, const boost::optional<cryptonote::network_type> & network_type){ + CHECK_AND_ASSERT_THROW_MES(!payment_id || !subaddress || subaddress->is_zero(), "Subaddress cannot be integrated"); TREZOR_AUTO_LOCK_CMD(); require_connected(); device_state_reset_unsafe(); @@ -218,6 +226,14 @@ namespace trezor { auto req = std::make_shared<messages::monero::MoneroGetAddress>(); this->set_msg_addr<messages::monero::MoneroGetAddress>(req.get(), path, network_type); + req->set_show_display(show_address); + if (subaddress){ + req->set_account(subaddress->major); + req->set_minor(subaddress->minor); + } + if (payment_id){ + req->set_payment_id(std::string(payment_id->data, 8)); + } auto response = this->client_exchange<messages::monero::MoneroAddress>(req); MTRACE("Get address response received"); diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp index 0e91847dc..a26a42788 100644 --- a/src/device_trezor/device_trezor.hpp +++ b/src/device_trezor/device_trezor.hpp @@ -110,6 +110,7 @@ namespace trezor { /* ======================================================================= */ bool get_public_address(cryptonote::account_public_address &pubkey) override; bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override; + void display_address(const cryptonote::subaddress_index& index, const boost::optional<crypto::hash8> &payment_id) override; /* ======================================================================= */ /* TREZOR PROTOCOL */ @@ -119,6 +120,9 @@ namespace trezor { * Get address. Throws. */ std::shared_ptr<messages::monero::MoneroAddress> get_address( + const boost::optional<cryptonote::subaddress_index> & subaddress = boost::none, + const boost::optional<crypto::hash8> & payment_id = boost::none, + bool show_address = false, const boost::optional<std::vector<uint32_t>> & path = boost::none, const boost::optional<cryptonote::network_type> & network_type = boost::none); diff --git a/src/device_trezor/trezor/protocol.cpp b/src/device_trezor/trezor/protocol.cpp index 5fe08abbe..61e51be14 100644 --- a/src/device_trezor/trezor/protocol.cpp +++ b/src/device_trezor/trezor/protocol.cpp @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include "version.h" #include "protocol.hpp" #include <unordered_map> #include <set> @@ -502,6 +503,8 @@ namespace tx { tsx_data.set_num_inputs(static_cast<google::protobuf::uint32>(tx.sources.size())); tsx_data.set_mixin(static_cast<google::protobuf::uint32>(tx.sources[0].outputs.size() - 1)); tsx_data.set_account(tx.subaddr_account); + tsx_data.set_monero_version(std::string(MONERO_VERSION) + "|" + MONERO_VERSION_TAG); + tsx_data.set_hard_fork(m_aux_data->hard_fork ? m_aux_data->hard_fork.get() : 0); assign_to_repeatable(tsx_data.mutable_minor_indices(), tx.subaddr_indices.begin(), tx.subaddr_indices.end()); // Rsig decision diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 02a099811..43323be2c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -177,8 +177,8 @@ namespace " account tag <tag_name> <account_index_1> [<account_index_2> ...]\n" " account untag <account_index_1> [<account_index_2> ...]\n" " account tag_description <tag_name> <description>"); - const char* USAGE_ADDRESS("address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>]"); - const char* USAGE_INTEGRATED_ADDRESS("integrated_address [<payment_id> | <address>]"); + const char* USAGE_ADDRESS("address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> | device [<index>]]"); + const char* USAGE_INTEGRATED_ADDRESS("integrated_address [device] [<payment_id> | <address>]"); const char* USAGE_ADDRESS_BOOK("address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]"); const char* USAGE_SET_VARIABLE("set <option> [<value>]"); const char* USAGE_GET_TX_KEY("get_tx_key <txid>"); @@ -8501,6 +8501,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std:: // address all // address <index_min> [<index_max>] // address label <index> <label text with white spaces allowed> + // address device [<index>] std::vector<std::string> local_args = args; tools::wallet2::transfer_container transfers; @@ -8537,6 +8538,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std:: label = tr("(Untitled address)"); m_wallet->add_subaddress(m_current_subaddress_account, label); print_address_sub(m_wallet->get_num_subaddresses(m_current_subaddress_account) - 1); + m_wallet->device_show_address(m_current_subaddress_account, m_wallet->get_num_subaddresses(m_current_subaddress_account) - 1, boost::none); } else if (local_args.size() >= 2 && local_args[0] == "label") { @@ -8585,6 +8587,27 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std:: for (index = index_min; index <= index_max; ++index) print_address_sub(index); } + else if (local_args[0] == "device") + { + index = 0; + local_args.erase(local_args.begin()); + if (local_args.size() > 0) + { + if (!epee::string_tools::get_xtype_from_string(index, local_args[0])) + { + fail_msg_writer() << tr("failed to parse index: ") << local_args[0]; + return true; + } + if (index >= m_wallet->get_num_subaddresses(m_current_subaddress_account)) + { + fail_msg_writer() << tr("<index> is out of bounds"); + return true; + } + } + + print_address_sub(index); + m_wallet->device_show_address(m_current_subaddress_account, index, boost::none); + } else { PRINT_USAGE(USAGE_ADDRESS); @@ -8596,12 +8619,29 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std:: bool simple_wallet::print_integrated_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { crypto::hash8 payment_id; - if (args.size() > 1) + bool display_on_device = false; + std::vector<std::string> local_args = args; + + if (local_args.size() > 0 && local_args[0] == "device") + { + local_args.erase(local_args.begin()); + display_on_device = true; + } + + auto device_show_integrated = [this, display_on_device](crypto::hash8 payment_id) + { + if (display_on_device) + { + m_wallet->device_show_address(m_current_subaddress_account, 0, payment_id); + } + }; + + if (local_args.size() > 1) { PRINT_USAGE(USAGE_INTEGRATED_ADDRESS); return true; } - if (args.size() == 0) + if (local_args.size() == 0) { if (m_current_subaddress_account != 0) { @@ -8611,9 +8651,10 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg payment_id = crypto::rand<crypto::hash8>(); success_msg_writer() << tr("Random payment ID: ") << payment_id; success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype()); + device_show_integrated(payment_id); return true; } - if(tools::wallet2::parse_short_payment_id(args.back(), payment_id)) + if(tools::wallet2::parse_short_payment_id(local_args.back(), payment_id)) { if (m_current_subaddress_account != 0) { @@ -8621,16 +8662,18 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg return true; } success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype()); + device_show_integrated(payment_id); return true; } else { address_parse_info info; - if(get_account_address_from_str(info, m_wallet->nettype(), args.back())) + if(get_account_address_from_str(info, m_wallet->nettype(), local_args.back())) { if (info.has_payment_id) { success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) % get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id); + device_show_integrated(info.payment_id); } else { diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 1711db482..a85e31474 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2419,6 +2419,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..57265470c 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -201,6 +201,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..7193eddd7 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1003,6 +1003,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/wallet2.cpp b/src/wallet/wallet2.cpp index c87947e39..8462c659d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -10048,6 +10048,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; @@ -10075,6 +10076,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); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 921c150cb..1ea10d333 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; |