mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 16:27:39 +00:00
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
This commit is contained in:
parent
5fbfa8a656
commit
f074b6b571
12 changed files with 128 additions and 7 deletions
2
external/trezor-common
vendored
2
external/trezor-common
vendored
|
@ -1 +1 @@
|
|||
Subproject commit cb238cb1f134accc4200217d9511115a8f61c6cb
|
||||
Subproject commit 31a0073c62738827b48d725facd3766879429124
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue