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
This commit is contained in:
Dusan Klinec
2019-02-23 15:28:18 +01:00
parent d74d26f2c9
commit a1fd1d499c
19 changed files with 1274 additions and 243 deletions
+17
View File
@@ -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);
+2
View File
@@ -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;
};
+81
View File
@@ -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;
+4
View File
@@ -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:
+45 -1
View File
@@ -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;
};
/**