aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
authorcslashm <cslashm@gmail.com>2018-03-26 12:55:48 +0200
committercslashm <cslashm@gmail.com>2018-03-31 18:00:33 +0200
commitc77d2bfaa0e0390e421b4d337f49451d504f7046 (patch)
treef9ad2766389b0efe78be3ff2dd9f5f65b7ed0f8f /src/wallet/wallet2.cpp
parentChange mutex lock model to avoid dead lock and ensure locks are always released. (diff)
downloadmonero-c77d2bfaa0e0390e421b4d337f49451d504f7046.tar.xz
Add the possibility to export private view key for fast scan.
On client startup the device asks for authorization to export the private view key. If user agree, the client hold the private view key allowing a fast blockchain scan. If the user does not agree, the blockchain scan is fully done via the device.
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp55
1 files changed, 44 insertions, 11 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 4b7e6dd93..295fcc1be 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1007,13 +1007,16 @@ void wallet2::set_unspent(size_t idx)
//----------------------------------------------------------------------------------------------------
void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const
{
+ hw::device &hwdev = m_account.get_device();
+ std::unique_lock<hw::device> hwdev_lock (hwdev);
+ hwdev.set_mode(hw::device::TRANSACTION_PARSE);
if (o.target.type() != typeid(txout_to_key))
{
tx_scan_info.error = true;
LOG_ERROR("wrong type id in transaction out");
return;
}
- tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, m_account.get_device());
+ tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, hwdev);
if(tx_scan_info.received)
{
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
@@ -1080,9 +1083,15 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi
//----------------------------------------------------------------------------------------------------
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen)
{
- // In this function, tx (probably) only contains the base information
- // (that is, the prunable stuff may or may not be included)
+ //ensure device is let in NONE mode in any case
+ hw::device &hwdev = m_account.get_device();
+
+ std::unique_lock<hw::device> hwdev_lock (hwdev);
+ hw::reset_mode rst(hwdev);
+ hwdev_lock.unlock();
+ // In this function, tx (probably) only contains the base information
+ // (that is, the prunable stuff may or may not be included)
if (!miner_tx && !pool)
process_unconfirmed(txid, tx, height);
std::vector<size_t> outs;
@@ -1119,8 +1128,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
tools::threadpool& tpool = tools::threadpool::getInstance();
tools::threadpool::waiter waiter;
const cryptonote::account_keys& keys = m_account.get_keys();
- hw::device &hwdev = m_account.get_device();
crypto::key_derivation derivation;
+
+ hwdev_lock.lock();
+ hwdev.set_mode(hw::device::TRANSACTION_PARSE);
if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation))
{
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
@@ -1140,6 +1151,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
additional_derivations.pop_back();
}
}
+ hwdev_lock.unlock();
if (miner_tx && m_refresh_type == RefreshNoCoinbase)
{
@@ -1161,16 +1173,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
std::ref(tx_scan_info[i])));
}
waiter.wait();
-
// then scan all outputs from 0
+ hwdev_lock.lock();
+ hwdev.set_mode(hw::device::NONE);
for (size_t i = 0; i < tx.vout.size(); ++i)
{
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
if (tx_scan_info[i].received)
{
+ hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
}
}
+ hwdev_lock.unlock();
}
}
else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1)
@@ -1181,14 +1196,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
std::ref(tx_scan_info[i])));
}
waiter.wait();
+
+ hwdev_lock.lock();
+ hwdev.set_mode(hw::device::NONE);
for (size_t i = 0; i < tx.vout.size(); ++i)
{
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
if (tx_scan_info[i].received)
{
+ hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
}
}
+ hwdev_lock.unlock();
}
else
{
@@ -1198,7 +1218,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
if (tx_scan_info[i].received)
{
+ hwdev_lock.lock();
+ hwdev.set_mode(hw::device::NONE);
+ hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
+ hwdev_lock.unlock();
}
}
}
@@ -7224,6 +7248,11 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
// usable balance.
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, bool trusted_daemon)
{
+ //ensure device is let in NONE mode in any case
+ hw::device &hwdev = m_account.get_device();
+ std::unique_lock<hw::device> hwdev_lock (hwdev);
+ hw::reset_mode rst(hwdev);
+
if(m_light_wallet) {
// Populate m_transfers
light_wallet_get_unspent_outs();
@@ -7441,8 +7470,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
unsigned int original_output_index = 0;
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
- hw::device &hwdev = m_account.get_device();
- hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
+
+ hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE);
while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) {
TX &tx = txes.back();
@@ -7671,7 +7700,7 @@ skip_tx:
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
" total fee, " << print_money(accumulated_change) << " total change");
- hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
+ hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL);
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
{
TX &tx = *i;
@@ -7802,6 +7831,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon)
{
+ //ensure device is let in NONE mode in any case
+ hw::device &hwdev = m_account.get_device();
+ std::unique_lock<hw::device> hwdev_lock (hwdev);
+ hw::reset_mode rst(hwdev);
+
uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
struct TX {
std::vector<size_t> selected_transfers;
@@ -7834,8 +7868,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
needed_fee = 0;
// while we have something to send
- hw::device &hwdev = m_account.get_device();
- hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
+ hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE);
while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) {
TX &tx = txes.back();
@@ -7921,7 +7954,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
" total fee, " << print_money(accumulated_change) << " total change");
- hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
+ hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL);
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
{
TX &tx = *i;