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.
This commit is contained in:
+44
-11
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user