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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user