@@ -2646,7 +2646,8 @@ void wallet2::process_new_scanned_transaction(
26462646 continue;
26472647 const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
26482648 auto it = m_key_images.find(in_to_key.k_image);
2649- if(it != m_key_images.end())
2649+ const bool key_image_known = it != m_key_images.end();
2650+ if(key_image_known)
26502651 {
26512652 transfer_details& td = m_transfers[it->second];
26522653 uint64_t amount = in_to_key.amount;
@@ -2683,7 +2684,9 @@ void wallet2::process_new_scanned_transaction(
26832684 }
26842685 }
26852686
2686- if (!pool && (m_track_uses || (m_background_syncing && it == m_key_images.end())))
2687+ const bool check_if_possibly_spent = !pool && (m_track_uses ||
2688+ (!key_image_known && (m_background_syncing || m_multisig)));
2689+ if (check_if_possibly_spent)
26872690 {
26882691 const uint64_t amount = in_to_key.amount;
26892692 std::vector<uint64_t> offsets = cryptonote::relative_output_offsets_to_absolute(in_to_key.key_offsets);
@@ -2709,12 +2712,12 @@ void wallet2::process_new_scanned_transaction(
27092712 const bool possibly_involved_with_tx = received_an_output || recognized_owned_possibly_spent_enote;
27102713 const bool should_cache_bg_tx = possibly_involved_with_tx
27112714 && !pool
2712- && m_background_syncing
2715+ && ( m_background_syncing || m_multisig)
27132716 && !m_background_sync_data.txs.count(txid);
27142717 if (should_cache_bg_tx)
27152718 {
2716- // we're going to re-process this receive when background sync is disabled
2717- if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
2719+ // we're going to re-process this tx when we can generate the key images for receives
2720+ if (m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
27182721 {
27192722 size_t bgs_idx = m_background_sync_data.txs.size();
27202723 background_synced_tx_t bgs_tx = {
@@ -2725,7 +2728,7 @@ void wallet2::process_new_scanned_transaction(
27252728 .block_timestamp = ts,
27262729 .double_spend_seen = double_spend_seen
27272730 };
2728- LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
2731+ LOG_PRINT_L2("Adding tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
27292732 m_background_sync_data.txs.insert({txid, std::move(bgs_tx)});
27302733 }
27312734 }
@@ -4564,7 +4567,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
45644567 }
45654568
45664569 m_first_refresh_done = true;
4567- if (m_background_syncing || m_is_background_wallet)
4570+ if (m_background_syncing || m_is_background_wallet || m_multisig )
45684571 m_background_sync_data.first_refresh_done = true;
45694572
45704573 m_multisig_rescan_info = std::vector<std::vector<tools::wallet2::multisig_info>>{};
@@ -5957,6 +5960,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
59575960
59585961 create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
59595962 setup_new_blockchain();
5963+ reset_background_sync_data(m_background_sync_data);
59605964
59615965 if (!wallet_.empty())
59625966 store();
@@ -6289,6 +6293,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
62896293 this->create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
62906294
62916295 this->setup_new_blockchain();
6296+ this->reset_background_sync_data(m_background_sync_data);
62926297
62936298 if (!m_wallet_file.empty())
62946299 this->store();
@@ -6518,7 +6523,7 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
65186523 store_background_keys(m_custom_background_key.get());
65196524 store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/);
65206525 }
6521- else if (m_background_sync_type == BackgroundSyncReusePassword)
6526+ else if (m_background_sync_type == BackgroundSyncReusePassword || m_multisig )
65226527 {
65236528 reset_background_sync_data(m_background_sync_data);
65246529 }
@@ -6860,8 +6865,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
68606865
68616866 try
68626867 {
6863- if (use_fs)
6864- process_background_cache_on_open();
6868+ process_background_cache_on_open();
68656869 }
68666870 catch (const std::exception &e)
68676871 {
@@ -6992,6 +6996,12 @@ void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf)
69926996//----------------------------------------------------------------------------------------------------
69936997void wallet2::process_background_cache_on_open()
69946998{
6999+ if (m_multisig)
7000+ {
7001+ if (!m_background_sync_data.first_refresh_done)
7002+ reset_background_sync_data(m_background_sync_data);
7003+ return;
7004+ }
69957005 if (m_wallet_file.empty())
69967006 return;
69977007 if (m_background_syncing || m_is_background_wallet)
@@ -8453,13 +8463,11 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
84538463 // sanity checks
84548464 for (const auto &ptx: exported_txs.m_ptx)
84558465 {
8456- CHECK_AND_ASSERT_MES(ptx.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched selected_transfers/vin sizes");
8457- for (size_t idx: ptx.selected_transfers)
8458- CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8459- CHECK_AND_ASSERT_MES(get_construction_data(ptx).selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8460- for (size_t idx: get_construction_data(ptx).selected_transfers)
8466+ const tools::wallet2::tx_construction_data &sd = get_construction_data(ptx);
8467+ CHECK_AND_ASSERT_MES(sd.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8468+ for (size_t idx: sd.selected_transfers)
84618469 CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8462- CHECK_AND_ASSERT_MES(get_construction_data(ptx) .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
8470+ CHECK_AND_ASSERT_MES(sd .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
84638471 }
84648472
84658473 return true;
@@ -14017,7 +14025,7 @@ void wallet2::process_background_cache(const background_sync_data_t &background_
1401714025 m_processing_background_cache = false;
1401814026 });
1401914027
14020- if (m_background_syncing || m_multisig || m_watch_only || key_on_device())
14028+ if (m_background_syncing || m_watch_only || key_on_device())
1402114029 return;
1402214030
1402314031 if (!background_sync_data.first_refresh_done)
@@ -15066,32 +15074,35 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1506615074 std::sort(m_multisig_rescan_info.begin(), m_multisig_rescan_info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)) < 0; });
1506715075 }
1506815076
15069- // first pass to determine where to detach the blockchain
15070- for (size_t n = 0; n < n_outputs; ++n)
15077+ for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
1507115078 {
15072- const transfer_details &td = m_transfers[n];
15073- if (!td.m_key_image_partial)
15079+ update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15080+ }
15081+
15082+ // The background cache should have all txs saved which need to be rescanned, including potential spends. We process
15083+ // the background cache with multisig info loaded.
15084+ const background_sync_data_t background_sync_data = m_background_sync_data;
15085+ const hashchain blockchain = m_blockchain;
15086+ const TreeCacheV1 tree_cache = m_tree_cache;
15087+ process_background_cache(background_sync_data, blockchain, m_last_block_reward, tree_cache);
15088+
15089+ // Once all key images are known and we've processed the background cache, any txs present in the background
15090+ // cache are no longer useful to us. They've been processed, we can remove them.
15091+ bool all_kis_known = true;
15092+ for (const auto &td : m_transfers)
15093+ {
15094+ if (td.m_key_image_known)
1507415095 continue;
15075- // FIXME: if we need to pop more blocks from the tree cache than the reorg depth, and the wallet has received
15076- // outputs from before the detach height, then the wallet won't be able to correct those prior output paths.
15077- // Some solutions:
15078- // A) restart sync from the wallet's first received output height.
15079- // B) re-request output paths from the daemon.
15080- // C) multisig wallet should stop syncing upon identifying a receive.
15081- MINFO("Multisig info importing from block height " << td.m_block_height);
15082- auto output_tracker_cache = create_output_tracker_cache();
15083- handle_reorg(td.m_block_height, output_tracker_cache);
15096+ all_kis_known = false;
1508415097 break;
1508515098 }
1508615099
15087- for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n )
15100+ if (all_kis_known )
1508815101 {
15089- update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15102+ MDEBUG("All key images are known, clearing background sync data since we don't need it anymore");
15103+ reset_background_sync_data(m_background_sync_data);
1509015104 }
1509115105
15092-
15093- refresh(false);
15094-
1509515106 return n_outputs;
1509615107}
1509715108//----------------------------------------------------------------------------------------------------
0 commit comments