@@ -2654,7 +2654,8 @@ void wallet2::process_new_scanned_transaction(
26542654 continue;
26552655 const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
26562656 auto it = m_key_images.find(in_to_key.k_image);
2657- if(it != m_key_images.end())
2657+ const bool key_image_known = it != m_key_images.end();
2658+ if(key_image_known)
26582659 {
26592660 transfer_details& td = m_transfers[it->second];
26602661 uint64_t amount = in_to_key.amount;
@@ -2691,7 +2692,9 @@ void wallet2::process_new_scanned_transaction(
26912692 }
26922693 }
26932694
2694- if (!pool && (m_track_uses || (m_background_syncing && it == m_key_images.end())))
2695+ const bool check_if_possibly_spent = !pool && (m_track_uses ||
2696+ (!key_image_known && (m_background_syncing || m_multisig)));
2697+ if (check_if_possibly_spent)
26952698 {
26962699 const uint64_t amount = in_to_key.amount;
26972700 std::vector<uint64_t> offsets = cryptonote::relative_output_offsets_to_absolute(in_to_key.key_offsets);
@@ -2717,12 +2720,12 @@ void wallet2::process_new_scanned_transaction(
27172720 const bool possibly_involved_with_tx = received_an_output || recognized_owned_possibly_spent_enote;
27182721 const bool should_cache_bg_tx = possibly_involved_with_tx
27192722 && !pool
2720- && m_background_syncing
2723+ && ( m_background_syncing || m_multisig)
27212724 && !m_background_sync_data.txs.count(txid);
27222725 if (should_cache_bg_tx)
27232726 {
2724- // we're going to re-process this receive when background sync is disabled
2725- if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
2727+ // we're going to re-process this tx when we can generate the key images for receives
2728+ if (m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
27262729 {
27272730 size_t bgs_idx = m_background_sync_data.txs.size();
27282731 background_synced_tx_t bgs_tx = {
@@ -2733,7 +2736,7 @@ void wallet2::process_new_scanned_transaction(
27332736 .block_timestamp = ts,
27342737 .double_spend_seen = double_spend_seen
27352738 };
2736- LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
2739+ LOG_PRINT_L2("Adding tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
27372740 m_background_sync_data.txs.insert({txid, std::move(bgs_tx)});
27382741 }
27392742 }
@@ -4605,7 +4608,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
46054608 }
46064609
46074610 m_first_refresh_done = true;
4608- if (m_background_syncing || m_is_background_wallet)
4611+ if (m_background_syncing || m_is_background_wallet || m_multisig )
46094612 m_background_sync_data.first_refresh_done = true;
46104613
46114614 m_multisig_rescan_info = std::vector<std::vector<tools::wallet2::multisig_info>>{};
@@ -5999,6 +6002,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
59996002
60006003 create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
60016004 setup_new_blockchain();
6005+ reset_background_sync_data(m_background_sync_data);
60026006
60036007 if (!wallet_.empty())
60046008 store();
@@ -6331,6 +6335,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
63316335 this->create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
63326336
63336337 this->setup_new_blockchain();
6338+ this->reset_background_sync_data(m_background_sync_data);
63346339
63356340 if (!m_wallet_file.empty())
63366341 this->store();
@@ -6560,7 +6565,7 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
65606565 store_background_keys(m_custom_background_key.get());
65616566 store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/);
65626567 }
6563- else if (m_background_sync_type == BackgroundSyncReusePassword)
6568+ else if (m_background_sync_type == BackgroundSyncReusePassword || m_multisig )
65646569 {
65656570 reset_background_sync_data(m_background_sync_data);
65666571 }
@@ -6875,8 +6880,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
68756880
68766881 try
68776882 {
6878- if (use_fs)
6879- process_background_cache_on_open();
6883+ process_background_cache_on_open();
68806884 }
68816885 catch (const std::exception &e)
68826886 {
@@ -7007,6 +7011,12 @@ void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf)
70077011//----------------------------------------------------------------------------------------------------
70087012void wallet2::process_background_cache_on_open()
70097013{
7014+ if (m_multisig)
7015+ {
7016+ if (!m_background_sync_data.first_refresh_done)
7017+ reset_background_sync_data(m_background_sync_data);
7018+ return;
7019+ }
70107020 if (m_wallet_file.empty())
70117021 return;
70127022 if (m_background_syncing || m_is_background_wallet)
@@ -8469,14 +8479,15 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
84698479 for (const auto &ptx: exported_txs.m_ptx)
84708480 {
84718481 CHECK_AND_ASSERT_MES(ptx.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched selected_transfers/vin sizes");
8482+ const tools::wallet2::tx_construction_data &sd = get_construction_data(ptx);
84728483 for (size_t idx: ptx.selected_transfers)
84738484 CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8474- CHECK_AND_ASSERT_MES(get_construction_data(ptx) .selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8475- for (size_t idx: get_construction_data(ptx) .selected_transfers)
8485+ CHECK_AND_ASSERT_MES(sd .selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8486+ for (size_t idx: sd .selected_transfers)
84768487 CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8477- CHECK_AND_ASSERT_MES(get_construction_data(ptx) .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
8488+ CHECK_AND_ASSERT_MES(sd .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
84788489 CHECK_AND_ASSERT_MES(!ptx.tx.vin.empty(), false, "Multisig tx has no inputs");
8479- CHECK_AND_ASSERT_MES(!get_construction_data(ptx) .sources.empty(), false, "Multisig tx has no sources");
8490+ CHECK_AND_ASSERT_MES(!sd .sources.empty(), false, "Multisig tx has no sources");
84808491 }
84818492
84828493 return true;
@@ -13960,7 +13971,7 @@ void wallet2::process_background_cache(const background_sync_data_t &background_
1396013971 m_processing_background_cache = false;
1396113972 });
1396213973
13963- if (m_background_syncing || m_multisig || m_watch_only || key_on_device())
13974+ if (m_background_syncing || m_watch_only || key_on_device())
1396413975 return;
1396513976
1396613977 if (!background_sync_data.first_refresh_done)
@@ -15088,32 +15099,35 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
1508815099 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; });
1508915100 }
1509015101
15091- // first pass to determine where to detach the blockchain
15092- for (size_t n = 0; n < n_outputs; ++n)
15102+ for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
1509315103 {
15094- const transfer_details &td = m_transfers[n];
15095- if (!td.m_key_image_partial)
15104+ update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15105+ }
15106+
15107+ // The background cache should have all txs saved which need to be rescanned, including potential spends. We process
15108+ // the background cache with multisig info loaded.
15109+ const background_sync_data_t background_sync_data = m_background_sync_data;
15110+ const hashchain blockchain = m_blockchain;
15111+ const TreeCacheV1 tree_cache = m_tree_cache;
15112+ process_background_cache(background_sync_data, blockchain, m_last_block_reward, tree_cache);
15113+
15114+ // Once all key images are known and we've processed the background cache, any txs present in the background
15115+ // cache are no longer useful to us. They've been processed, we can remove them.
15116+ bool all_kis_known = true;
15117+ for (const auto &td : m_transfers)
15118+ {
15119+ if (td.m_key_image_known)
1509615120 continue;
15097- // FIXME: if we need to pop more blocks from the tree cache than the reorg depth, and the wallet has received
15098- // outputs from before the detach height, then the wallet won't be able to correct those prior output paths.
15099- // Some solutions:
15100- // A) restart sync from the wallet's first received output height.
15101- // B) re-request output paths from the daemon.
15102- // C) multisig wallet should stop syncing upon identifying a receive.
15103- MINFO("Multisig info importing from block height " << td.m_block_height);
15104- auto output_tracker_cache = create_output_tracker_cache();
15105- handle_reorg(td.m_block_height, output_tracker_cache);
15121+ all_kis_known = false;
1510615122 break;
1510715123 }
1510815124
15109- for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n )
15125+ if (all_kis_known )
1511015126 {
15111- update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15127+ MDEBUG("All key images are known, clearing background sync data since we don't need it anymore");
15128+ reset_background_sync_data(m_background_sync_data);
1511215129 }
1511315130
15114- if (refresh_after_import)
15115- refresh(false);
15116-
1511715131 return n_outputs;
1511815132}
1511915133//----------------------------------------------------------------------------------------------------
0 commit comments