aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorDusan Klinec <dusan.klinec@gmail.com>2019-02-23 15:28:18 +0100
committerDusan Klinec <dusan.klinec@gmail.com>2019-03-20 21:11:02 +0100
commita1fd1d499c6a967d2cd011c57eb79f6ebc5847f4 (patch)
tree9bb84d4da61e0a2c4c5552d27452397b8248cb88 /src/wallet
parentcrypto: hmac_keccak added (diff)
downloadmonero-a1fd1d499c6a967d2cd011c57eb79f6ebc5847f4.tar.xz
device/trezor: HF10 support added, wallet::API
- import only key images generated by cold signing process - wallet_api: trezor methods added - wallet: button request code added - const added to methods - wallet2::get_tx_key_device() tries to decrypt stored tx private keys using the device. - simplewallet supports get_tx_key and get_tx_proof on hw device using the get_tx_key feature - live refresh enables refresh with trezor i.e. computing key images on the fly. More convenient and efficient for users. - device: has_ki_live_refresh added - a thread is watching whether live refresh is being computed, if not for 30 seconds, it terminates the live refresh process - switches Trezor state
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/pending_transaction.cpp17
-rw-r--r--src/wallet/api/pending_transaction.h2
-rw-r--r--src/wallet/api/wallet.cpp81
-rw-r--r--src/wallet/api/wallet.h4
-rw-r--r--src/wallet/api/wallet2_api.h46
-rw-r--r--src/wallet/wallet2.cpp167
-rw-r--r--src/wallet/wallet2.h27
7 files changed, 306 insertions, 38 deletions
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index 913e3156f..4d602320f 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -109,6 +109,23 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
}
m_wallet.pauseRefresh();
+
+ const bool tx_cold_signed = m_wallet.m_wallet->get_account().get_device().has_tx_cold_sign();
+ if (tx_cold_signed){
+ std::unordered_set<size_t> selected_transfers;
+ for(const tools::wallet2::pending_tx & ptx : m_pending_tx){
+ for(size_t s : ptx.selected_transfers){
+ selected_transfers.insert(s);
+ }
+ }
+
+ m_wallet.m_wallet->cold_tx_aux_import(m_pending_tx, m_tx_device_aux);
+ bool r = m_wallet.m_wallet->import_key_images(m_key_images, 0, selected_transfers);
+ if (!r){
+ throw runtime_error("Cold sign transaction submit failed - key image sync fail");
+ }
+ }
+
while (!m_pending_tx.empty()) {
auto & ptx = m_pending_tx.back();
m_wallet.m_wallet->commit_tx(ptx);
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
index 50b9f07ef..4f3b8a177 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
@@ -67,6 +67,8 @@ private:
std::string m_errorString;
std::vector<tools::wallet2::pending_tx> m_pending_tx;
std::unordered_set<crypto::public_key> m_signers;
+ std::vector<std::string> m_tx_device_aux;
+ std::vector<crypto::key_image> m_key_images;
};
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 44cd67657..8f9e571fe 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -242,6 +242,42 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
}
+ virtual void on_device_button_request(uint64_t code)
+ {
+ if (m_listener) {
+ m_listener->onDeviceButtonRequest(code);
+ }
+ }
+
+ virtual boost::optional<epee::wipeable_string> on_device_pin_request()
+ {
+ if (m_listener) {
+ auto pin = m_listener->onDevicePinRequest();
+ if (pin){
+ return boost::make_optional(epee::wipeable_string((*pin).data(), (*pin).size()));
+ }
+ }
+ return boost::none;
+ }
+
+ virtual boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device)
+ {
+ if (m_listener) {
+ auto passphrase = m_listener->onDevicePassphraseRequest(on_device);
+ if (!on_device && passphrase) {
+ return boost::make_optional(epee::wipeable_string((*passphrase).data(), (*passphrase).size()));
+ }
+ }
+ return boost::none;
+ }
+
+ virtual void on_device_progress(const hw::device_progress & event)
+ {
+ if (m_listener) {
+ m_listener->onDeviceProgress(DeviceProgress(event.progress(), event.indeterminate()));
+ }
+ }
+
WalletListener * m_listener;
WalletImpl * m_wallet;
};
@@ -785,6 +821,28 @@ bool WalletImpl::setPassword(const std::string &password)
return status() == Status_Ok;
}
+bool WalletImpl::setDevicePin(const std::string &pin)
+{
+ clearStatus();
+ try {
+ m_wallet->get_account().get_device().set_pin(epee::wipeable_string(pin.data(), pin.size()));
+ } catch (const std::exception &e) {
+ setStatusError(e.what());
+ }
+ return status() == Status_Ok;
+}
+
+bool WalletImpl::setDevicePassphrase(const std::string &passphrase)
+{
+ clearStatus();
+ try {
+ m_wallet->get_account().get_device().set_passphrase(epee::wipeable_string(passphrase.data(), passphrase.size()));
+ } catch (const std::exception &e) {
+ setStatusError(e.what());
+ }
+ return status() == Status_Ok;
+}
+
std::string WalletImpl::address(uint32_t accountIndex, uint32_t addressIndex) const
{
return m_wallet->get_subaddress_as_str({accountIndex, addressIndex});
@@ -1428,6 +1486,8 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
extra, subaddr_account, subaddr_indices);
}
+ pendingTxPostProcess(transaction);
+
if (multisig().isMultisig) {
transaction->m_signers = m_wallet->make_multisig_tx_set(transaction->m_pending_tx).m_signers;
}
@@ -1511,6 +1571,7 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
do {
try {
transaction->m_pending_tx = m_wallet->create_unmixable_sweep_transactions();
+ pendingTxPostProcess(transaction);
} catch (const tools::error::daemon_busy&) {
// TODO: make it translatable with "tr"?
@@ -2093,6 +2154,21 @@ bool WalletImpl::isNewWallet() const
return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !watchOnly();
}
+void WalletImpl::pendingTxPostProcess(PendingTransactionImpl * pending)
+{
+ // If the device being used is HW device with cold signing protocol, cold sign then.
+ if (!m_wallet->get_account().get_device().has_tx_cold_sign()){
+ return;
+ }
+
+ tools::wallet2::signed_tx_set exported_txs;
+ std::vector<cryptonote::address_parse_info> dsts_info;
+
+ m_wallet->cold_sign_tx(pending->m_pending_tx, exported_txs, dsts_info, pending->m_tx_device_aux);
+ pending->m_key_images = exported_txs.key_images;
+ pending->m_pending_tx = exported_txs.ptx;
+}
+
bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)
{
// claim RPC so there's no in-memory encryption for now
@@ -2325,6 +2401,11 @@ bool WalletImpl::isKeysFileLocked()
{
return m_wallet->is_keys_file_locked();
}
+
+uint64_t WalletImpl::coldKeyImageSync(uint64_t &spent, uint64_t &unspent)
+{
+ return m_wallet->cold_key_image_sync(spent, unspent);
+}
} // namespace
namespace Bitmonero = Monero;
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 55240d64f..f1f8f7e4d 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -89,6 +89,8 @@ public:
std::string errorString() const override;
void statusWithErrorString(int& status, std::string& errorString) const override;
bool setPassword(const std::string &password) override;
+ bool setDevicePin(const std::string &password) override;
+ bool setDevicePassphrase(const std::string &password) override;
std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const override;
std::string integratedAddress(const std::string &payment_id) const override;
std::string secretViewKey() const override;
@@ -198,6 +200,7 @@ public:
virtual bool lockKeysFile() override;
virtual bool unlockKeysFile() override;
virtual bool isKeysFileLocked() override;
+ virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override;
private:
void clearStatus() const;
@@ -209,6 +212,7 @@ private:
bool daemonSynced() const;
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);
private:
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 5c301974f..5410b827c 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -324,6 +324,19 @@ struct MultisigState {
uint32_t total;
};
+
+struct DeviceProgress {
+ DeviceProgress(): m_progress(0), m_indeterminate(false) {}
+ DeviceProgress(double progress, bool indeterminate=false): m_progress(progress), m_indeterminate(indeterminate) {}
+
+ virtual double progress() const { return m_progress; }
+ virtual bool indeterminate() const { return m_indeterminate; }
+
+protected:
+ double m_progress;
+ bool m_indeterminate;
+};
+
struct WalletListener
{
virtual ~WalletListener() = 0;
@@ -364,6 +377,31 @@ struct WalletListener
* @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously
*/
virtual void refreshed() = 0;
+
+ /**
+ * @brief called by device if the action is required
+ */
+ virtual void onDeviceButtonRequest(uint64_t code) {}
+
+ /**
+ * @brief called by device when PIN is needed
+ */
+ virtual optional<std::string> onDevicePinRequest() {
+ throw std::runtime_error("Not supported");
+ }
+
+ /**
+ * @brief called by device when passphrase entry is needed
+ */
+ virtual optional<std::string> onDevicePassphraseRequest(bool on_device) {
+ if (!on_device) throw std::runtime_error("Not supported");
+ return optional<std::string>();
+ }
+
+ /**
+ * @brief Signalizes device operation progress
+ */
+ virtual void onDeviceProgress(const DeviceProgress & event) {};
};
@@ -375,7 +413,8 @@ struct Wallet
{
enum Device {
Device_Software = 0,
- Device_Ledger = 1
+ Device_Ledger = 1,
+ Device_Trezor = 2
};
enum Status {
@@ -401,6 +440,8 @@ struct Wallet
//! returns both error and error string atomically. suggested to use in instead of status() and errorString()
virtual void statusWithErrorString(int& status, std::string& errorString) const = 0;
virtual bool setPassword(const std::string &password) = 0;
+ virtual bool setDevicePin(const std::string &password) { return false; };
+ virtual bool setDevicePassphrase(const std::string &password) { return false; };
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
std::string mainAddress() const { return address(0, 0); }
virtual std::string path() const = 0;
@@ -947,6 +988,9 @@ struct Wallet
* \return Device they are on
*/
virtual Device getDeviceType() const = 0;
+
+ //! cold-device protocol key image sync
+ virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) = 0;
};
/**
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 11be8fd6e..5c12ad800 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -929,22 +929,30 @@ wallet_keys_unlocker::~wallet_keys_unlocker()
}
}
-void wallet_device_callback::on_button_request()
+void wallet_device_callback::on_button_request(uint64_t code)
{
if (wallet)
- wallet->on_button_request();
+ wallet->on_device_button_request(code);
}
-void wallet_device_callback::on_pin_request(epee::wipeable_string & pin)
+boost::optional<epee::wipeable_string> wallet_device_callback::on_pin_request()
{
if (wallet)
- wallet->on_pin_request(pin);
+ return wallet->on_device_pin_request();
+ return boost::none;
}
-void wallet_device_callback::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase)
+boost::optional<epee::wipeable_string> wallet_device_callback::on_passphrase_request(bool on_device)
{
if (wallet)
- wallet->on_passphrase_request(on_device, passphrase);
+ return wallet->on_device_passphrase_request(on_device);
+ return boost::none;
+}
+
+void wallet_device_callback::on_progress(const hw::device_progress& event)
+{
+ if (wallet)
+ wallet->on_device_progress(event);
}
wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
@@ -2884,6 +2892,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
std::vector<parsed_block> parsed_blocks;
bool refreshed = false;
std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> output_tracker_cache;
+ hw::device &hwdev = m_account.get_device();
// pull the first set of blocks
get_short_chain_history(short_chain_history, (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
@@ -3040,6 +3049,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
LOG_PRINT_L1("Failed to check pending transactions");
}
+ hwdev.computing_key_images(false);
m_first_refresh_done = true;
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all()));
@@ -9644,6 +9654,7 @@ void wallet2::cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_
hw::wallet_shim wallet_shim;
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;
dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data);
tx_device_aux = aux_data.tx_device_aux;
@@ -9860,7 +9871,7 @@ void wallet2::discard_unmixable_outputs()
}
}
-bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const
+bool wallet2::get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const
{
additional_tx_keys.clear();
const std::unordered_map<crypto::hash, crypto::secret_key>::const_iterator i = m_tx_keys.find(txid);
@@ -9873,6 +9884,82 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s
return true;
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys)
+{
+ bool r = get_tx_key_cached(txid, tx_key, additional_tx_keys);
+ if (r)
+ {
+ return true;
+ }
+
+ auto & hwdev = get_account().get_device();
+
+ // So far only Cold protocol devices are supported.
+ if (hwdev.device_protocol() != hw::device::PROTOCOL_COLD)
+ {
+ return false;
+ }
+
+ const auto tx_data_it = m_tx_device.find(txid);
+ if (tx_data_it == m_tx_device.end())
+ {
+ MDEBUG("Aux data not found for txid: " << txid);
+ return false;
+ }
+
+ auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev);
+ CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
+ if (!dev_cold->is_get_tx_key_supported())
+ {
+ MDEBUG("get_tx_key not supported by the device");
+ return false;
+ }
+
+ hw::device_cold::tx_key_data_t tx_key_data;
+ dev_cold->load_tx_key_data(tx_key_data, tx_data_it->second);
+
+ // Load missing tx prefix hash
+ if (tx_key_data.tx_prefix_hash.empty())
+ {
+ COMMAND_RPC_GET_TRANSACTIONS::request req;
+ COMMAND_RPC_GET_TRANSACTIONS::response res;
+ req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
+ req.decode_as_json = false;
+ req.prune = true;
+ m_daemon_rpc_mutex.lock();
+ bool ok = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client);
+ m_daemon_rpc_mutex.unlock();
+ THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1),
+ error::wallet_internal_error, "Failed to get transaction from daemon");
+
+ cryptonote::transaction tx;
+ crypto::hash tx_hash{};
+ cryptonote::blobdata tx_data;
+ crypto::hash tx_prefix_hash{};
+ ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data);
+ THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
+ THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx, tx_hash, tx_prefix_hash),
+ error::wallet_internal_error, "Failed to validate transaction from daemon");
+ THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error,
+ "Failed to get the right transaction from daemon");
+
+ tx_key_data.tx_prefix_hash = std::string(tx_prefix_hash.data, 32);
+ }
+
+ std::vector<crypto::secret_key> tx_keys;
+ dev_cold->get_tx_key(tx_keys, tx_key_data, m_account.get_keys().m_view_secret_key);
+ if (tx_keys.empty())
+ {
+ return false;
+ }
+
+ tx_key = tx_keys[0];
+ tx_keys.erase(tx_keys.begin());
+ additional_tx_keys = tx_keys;
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys)
{
// fetch tx from daemon and check if secret keys agree with corresponding public keys
@@ -10275,7 +10362,8 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac
{
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
- THROW_WALLET_EXCEPTION_IF(!get_tx_key(txid, tx_key, additional_tx_keys), error::wallet_internal_error, "Tx secret key wasn't found in the wallet file.");
+ bool found_tx_key = get_tx_key(txid, tx_key, additional_tx_keys);
+ THROW_WALLET_EXCEPTION_IF(!found_tx_key, error::wallet_internal_error, "Tx secret key wasn't found in the wallet file.");
const size_t num_sigs = 1 + additional_tx_keys.size();
shared_secret.resize(num_sigs);
@@ -11448,29 +11536,48 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
return m_transfers[signed_key_images.size() - 1].m_block_height;
}
-bool wallet2::import_key_images(std::vector<crypto::key_image> key_images)
+bool wallet2::import_key_images(std::vector<crypto::key_image> key_images, size_t offset, boost::optional<std::unordered_set<size_t>> selected_transfers)
{
- if (key_images.size() > m_transfers.size())
+ if (key_images.size() + offset > m_transfers.size())
{
LOG_PRINT_L1("More key images returned that we know outputs for");
return false;
}
- for (size_t i = 0; i < key_images.size(); ++i)
+ for (size_t ki_idx = 0; ki_idx < key_images.size(); ++ki_idx)
{
- transfer_details &td = m_transfers[i];
- if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != key_images[i])
- LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one");
- td.m_key_image = key_images[i];
- m_key_images[m_transfers[i].m_key_image] = i;
+ const size_t transfer_idx = ki_idx + offset;
+ if (selected_transfers && selected_transfers.get().find(transfer_idx) == selected_transfers.get().end())
+ continue;
+
+ transfer_details &td = m_transfers[transfer_idx];
+ if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != key_images[ki_idx])
+ LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << ki_idx << ": trusting imported one");
+ td.m_key_image = key_images[ki_idx];
+ m_key_images[td.m_key_image] = transfer_idx;
td.m_key_image_known = true;
td.m_key_image_request = false;
td.m_key_image_partial = false;
- m_pub_keys[m_transfers[i].get_public_key()] = i;
+ m_pub_keys[td.get_public_key()] = transfer_idx;
}
return true;
}
+bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool only_selected_transfers)
+{
+ std::unordered_set<size_t> selected_transfers;
+ if (only_selected_transfers)
+ {
+ for (const pending_tx & ptx : signed_tx.ptx)
+ {
+ for (const size_t s: ptx.selected_transfers)
+ selected_transfers.insert(s);
+ }
+ }
+
+ return import_key_images(signed_tx.key_images, offset, only_selected_transfers ? boost::make_optional(selected_transfers) : boost::none);
+}
+
wallet2::payment_container wallet2::export_payments() const
{
payment_container payments;
@@ -12451,22 +12558,30 @@ wallet_device_callback * wallet2::get_device_callback()
}
return m_device_callback.get();
}//----------------------------------------------------------------------------------------------------
-void wallet2::on_button_request()
+void wallet2::on_device_button_request(uint64_t code)
{
- if (0 != m_callback)
- m_callback->on_button_request();
+ if (nullptr != m_callback)
+ m_callback->on_device_button_request(code);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::on_pin_request(epee::wipeable_string & pin)
+boost::optional<epee::wipeable_string> wallet2::on_device_pin_request()
{
- if (0 != m_callback)
- m_callback->on_pin_request(pin);
+ if (nullptr != m_callback)
+ return m_callback->on_device_pin_request();
+ return boost::none;
}
//----------------------------------------------------------------------------------------------------
-void wallet2::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase)
+boost::optional<epee::wipeable_string> wallet2::on_device_passphrase_request(bool on_device)
{
- if (0 != m_callback)
- m_callback->on_passphrase_request(on_device, passphrase);
+ if (nullptr != m_callback)
+ return m_callback->on_device_passphrase_request(on_device);
+ return boost::none;
+}
+//----------------------------------------------------------------------------------------------------
+void wallet2::on_device_progress(const hw::device_progress& event)
+{
+ if (nullptr != m_callback)
+ m_callback->on_device_progress(event);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_rpc_status(const std::string &s) const
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index b510a8f99..3e0944d85 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -103,9 +103,10 @@ namespace tools
virtual void on_lw_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount) {}
virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount) {}
// Device callbacks
- virtual void on_button_request() {}
- virtual void on_pin_request(epee::wipeable_string & pin) {}
- virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {}
+ virtual void on_device_button_request(uint64_t code) {}
+ virtual boost::optional<epee::wipeable_string> on_device_pin_request() { return boost::none; }
+ virtual boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device) { return boost::none; }
+ virtual void on_device_progress(const hw::device_progress& event) {};
// Common callbacks
virtual void on_pool_tx_removed(const crypto::hash &txid) {}
virtual ~i_wallet2_callback() {}
@@ -115,9 +116,10 @@ namespace tools
{
public:
wallet_device_callback(wallet2 * wallet): wallet(wallet) {};
- void on_button_request() override;
- void on_pin_request(epee::wipeable_string & pin) override;
- void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) override;
+ void on_button_request(uint64_t code=0) override;
+ boost::optional<epee::wipeable_string> on_pin_request() override;
+ boost::optional<epee::wipeable_string> on_passphrase_request(bool on_device) override;
+ void on_progress(const hw::device_progress& event) override;
private:
wallet2 * wallet;
};
@@ -1004,8 +1006,9 @@ namespace tools
const std::string & device_derivation_path() const { return m_device_derivation_path; }
void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; }
- bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
+ bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys);
+ bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys);
void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message);
@@ -1127,7 +1130,8 @@ namespace tools
std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const;
uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true);
uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent);
- bool import_key_images(std::vector<crypto::key_image> key_images);
+ bool import_key_images(std::vector<crypto::key_image> key_images, size_t offset=0, boost::optional<std::unordered_set<size_t>> selected_transfers=boost::none);
+ bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false);
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
void update_pool_state(bool refreshed = false);
@@ -1333,9 +1337,10 @@ namespace tools
void create_keys_file(const std::string &wallet_, bool watch_only, const epee::wipeable_string &password, bool create_address_file);
wallet_device_callback * get_device_callback();
- void on_button_request();
- void on_pin_request(epee::wipeable_string & pin);
- void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase);
+ void on_device_button_request(uint64_t code);
+ boost::optional<epee::wipeable_string> on_device_pin_request();
+ boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device);
+ void on_device_progress(const hw::device_progress& event);
std::string get_rpc_status(const std::string &s) const;
void throw_on_rpc_response_error(const boost::optional<std::string> &status, const char *method) const;